PHP垃圾回收机制(GarbageCollection . GC)
PHP把变量保存在zval容器里面。容器,,container,可以想像成一块存储区域,或者一个盒子。
盒子里面包括以下几部分
(1) Type: string
(2) Value:this is
(3) Is_ref: // 是否为引用 bool 值
(4) Refcount: // 引用计数次数也就是被引用了几次当refcount为0的时候,该容器会被删除掉,释放空间出来。当refcount为1的时候,is_ref必须为0。
其中一个叫做”is_ref”, 它是一个bool型的值,占用一个bit,表示该zval容器(也就是这个变量)是否被引用。
php就是使用这个bit来判断变量是个普通变量,或者是个引用(reference)。
说起来,PHP有二种引用:
其一是用户代码中的&
其二是PHP内部实现的引用计数机制(internal reference counting mechanism),用来优化内存使用的。
is_ref是指&
zval容器中的另外一部分,是”refcount”,引用计数。用来记录有多少个变量指向这个zval容器。
通常吧,这个时候我们只说symbol(符号),不说variables(变量),其实是同一个意思。
当refcount为1的时候,is_ref必须为0。
当refcount为0的时候,该容器会被删除掉,释放空间出来。
所有的symbol保存在一张symbol table里面(符号表)。
php维护了很多张这样的表,GLOBAL一张,每个函数一张。类的每个方法也有一张。
基本上是按照变量的作用域(scope)来建表的。
当我们用一个constant value(常量)来为变量赋值的时候,zval容器才会被创建出来。
$a = "this is";
Zval容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:false
(4)Refcount : 1 ;
(二) 变量的赋值
$a = "this is";
$b = $a;
$c = $a ;
Zval 容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:false
(4)Refcount : 3 ; 表示有3个符号指向这个容器
但是如果产生了新的内容,php则会创建一个zval容器
$a = "this is";
$b = $a;
$c = $a ;
$c = 12 ;
Zval(1) 容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:false
(4)Refcount : 2 ; 表示有2个符号指向这个容器
Zval(2) 为$c新创建一个容器对应的关系为
(1)Type :int
(2)Value: 2
(3)Is_ref:false
(4)Refcount : 1 ; 表示有1个符号指向这个容器
(三) 变量的引用
$a = "this is";
$b =& $a;
$c = &$a ;
Zval 容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:true
(4)Refcount : 3 ; 表示有3个符号指向这个容器
符号a b和c都指向同一个容器,而且这个容器的is_ref位为1(因为&出现了)
引用赋值与普通赋值的区别就在于容器的is_ref位为1还是为0。如果为1,改变任意一个变量的值,只是会更改容器的值。如果为0,改变任意一个变量的值,都会创建一个新的容器出来。
(四) 变量赋值与引用
$a = "this is";
$b =$a;
$c = &$a ;
// 此会产生两个zval容器
Zval(1) 容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:false 非引用,这里是$a 所指
(4)Refcount : 1 ; 表示有3个符号指向这个容器
Zval(2) 容器对应的关系为
(1)Type :string
(2)Value: this is
(3)Is_ref:true 是引用,这里是$C=&$a 所指
(4)Refcount : 2 ; 表示有2个符号($b,$c)指向这个容器
(五) PHP如何处理数组和对象
每个数组都维护了一张自己的符号表,保存了自己的元素。看代码:
$a = array( "meaning" => "life", "number" => 42 );
xdebug_debug_zval( "a" );
会显示:
ais_ref=0)=array (
"meaning" is_ref=0)="life",
"number" is_ref
)
$a =array("one");
$a[] = &$a;
unset($a);
参考文献
// 大数据
以诚感人者,人亦诚而应。