邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

php7内核读书笔记-第四章 内存管理
php7内核读书笔记-第四章 内存管理
引用计数
会使用引用计数机制的类型
type refcounted
simple types
string Y
interned string N(内部字符串,request完成后统一销毁释放 $a="hi")
array Y
imutable array N(不可变数组)
object Y
resource Y
reference Y

垃圾回收
ps:如果一个变量value的refcount减少到了0,那么此value可以被释放掉,不属于垃圾;如果一个变量value的refcount减少之后大于0,那么此value还不能被释放,此value可能成为一个垃圾(例子 $a=array(1);$a[]=$a;unset($a);)。
回收算法
php内存管理之引用计数
<?php
$a = 'Hello World';
$b = $a;
unset($a);  
?>

第一条语句执行后,PHP创建了$a这个变量,并为它申请了12B的内存来存放"hello world"这个字符串. 紧接着把$a赋给了$b,并释放掉$a;
PHP变量的名称和值在内核中是保存在两个不同的地方的,值是通过一个与名字毫无关系的zval结构来保存,而这个变量的名字a则保存在符号表里,两者之间通过指针联系着.
现在我们检查$a和$b两个变量,他们的值指向了"hello world"这个字符串在内存中的位置. zval的四个成员value、type、is_ref__gc、refcount__gc,
当一个变量被第一次创建的时候,它对应的zval结构体的refcount__gc成员的值会被初始化为1,理由很简单,因为只有这个变量自己在用它。但是当你把这个变量赋值给别的变量时,refcount__gc属性便会加1变成2,因为现在有两个变量在用这个zval结构了! 
这个时候当我们再用unset删除$a的时候,它删除符号表里的$a的信息,然后清理它的值部分,这时它发现$a的值对应的zval结构的refcount值是2,也就是有另外一个变量在一起用着这个zval,所以unset只需把这个zval的refcount减去1就行了!

写时复制机制
<?php
$a = 1;
$b = $a;
$b += 5;
?>
从代码逻辑来看,我们希望语句执行后$a仍然是1,而$b则需要变成6。我们知道在第二句完成后内核通过让$a和$b共享一个zval结构来达到节省内存的目的,但是现在第三句来了,这时$b的改变应该怎样在内核中实现呢? 答案非常简单,内核首先查看refcount__gc属性,如果它大于1则为这个变化的变量从原zval结构中复制出一份新的专属与$b的zval来,并改变其值。
现在$b变量拥有了自己的zval,并且可以自由的修改它的值了。

Change on Write
<?php
    $a = 1;
    $b = &$a;
    $b += 5;
?>
我们都知道$a的值也变成6了。当我们更改$b的值时,内核发现$b是$a的一个用户端引用,也就是所它可以直接改变$b对应的zval的值,而无需再为它生成一个新的不同与$a的zval。因为他知道$a和$b都想得到这次变化! 但是内核是怎么知道这一切的呢?简单的讲,它是通过zval的is_ref__gc成员来获取这些信息的。这个成员只有两个值,就像开关的开与关一样。它的这两个状态代表着它是否是一个用户在PHP语言中定义的引用。在第一条语句($a = 1;)执行完毕后,$a对应的zval的refcount__gc等于1,is_ref__gc等于0;。 当第二条语句执行后($b = &$a;),refcount__gc属性向往常一样增长为2,而且is_ref__gc属性也同时变为了1! 最后,在执行第三条语句的时候,内核再次检查$b的zval以确定是否需要复制出一份新的zval结构来,这次不需要复制,因为我们刚才上面的get_var_and_separate函数其实是个简化版,并且少写了一个条件:
/* 如果这个zval在php语言中是通过引用的形式存在的,或者它的refcount小于2,则不许要复制。*/
if ((*varval)->is_ref || (*varval)->refcount < 2) {
    return *varval;
}   
这一次,尽管它的refcount等于2,但是因为它的is_ref等于1,所以也不会被复制。内核会直接的修改这个zval的值


Separation Anxiety
<?php
$a = 1;
$b = $a;
$c = &$a; 
?>
03fig03.jpg

<?php
$a = 1;
$b = &$a;
$c = $a; 
?>

03fig02.jpg


PS:http://www.walu.cc/phpbook/3.2.md



优惠券
最新微语