php中的变量存储在变量容器zval中,zval中除了存储变量类型和值外,还有is_ref和refcount字段。 refcount表示指向变量的元素个数,is_ref表示变量是否有别名。如果refcount为0时,就回收该变量容器。如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理。
安装xdebug扩展之后,可以利用xdebug_debug_zval打印出zval容器详情。
这里有一点需要注意,将一个变量 = 赋值给另一个变量时,不会立即为新变量分配内存空间,而是在原变量的zval中给refcount加1。 只有当原变量或者发生改变时,才会为新变量分配内存空间,同时原变量的refcount减 1 。当然,如果unset原变量,新变量直接就使用原变量的zval而不是重新分配。
&引用赋值时,原变量的is_ref 变为1,refcount 加1. ?如果给一个变量&赋值,之前 = 赋值的变量会分配空间。
$a
= 1;
xdebug_debug_zval(
'a'
);
echo
PHP_EOL;
$b
=
$a
;
xdebug_debug_zval(
'a'
);
echo
PHP_EOL;
$c
= &
$a
;
xdebug_debug_zval(
'a'
);
echo
PHP_EOL;
xdebug_debug_zval(
'b'
);
echo
PHP_EOL;
?>
运行结果如下:
a:(refcount=1, is_ref=0),
int 1 a:(refcount=2, is_ref=0),
int 1 a:(refcount=2, is_ref=1),
int 1 b:(refcount=1, is_ref=0),
int 1
在php5.3的GC中,针对的垃圾做了如下说明:
1:如果一个zval的refcount增加,那么此zval还在使用,肯定不是垃圾,不会进入缓冲区
2:如果一个zval的refcount减少到0, 那么zval会被立即释放掉,不属于GC要处理的垃圾对象,不会进入缓冲区。
3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾,将其放入缓冲区。
PHP5.3中的GC针对的就是这种zval进行的处理。 开启/关闭垃圾回收机制可以通过修改php配置实现,也可以在程序中使用gc_enable() 和 gc_disable()开启和关闭。