1.1.1. 垃圾回收机制

PHP 的内部变量中包含两个字节:

  1. 一个是 is_ref ,布尔值,用来标识该变量是否是引用。通过这个字节将普通变量和引用变量区分开。
  2. 第二个是 refcount,表示指向这个变量的变量有多少个。

当发生 unset 时,会减少 refcount

<?php
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
unset( $b, $c );
xdebug_debug_zval( 'a' );
?>

结果为:

a: (refcount=3, is_ref=0)='new string'
a: (refcount=1, is_ref=0)='new string'

在数组中:

<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
$a['life'] = $a['meaning'];
xdebug_debug_zval( 'a' );
?>
a: (refcount=1, is_ref=0)=array (
   'meaning' => (refcount=2, is_ref=0)='life',
   'number' => (refcount=1, is_ref=0)=42,
   'life' => (refcount=2, is_ref=0)='life'
)

回收周期

清理垃圾有两个准则:

  1. 如果一个变量 value 的 refcount 减少到 0,则 value 会被释放掉,不属于垃圾。
  2. 如果一个变量 value 的 refcount 减小后仍大于 0,则此 zval 还不能被释放掉,但可能是一个垃圾。

垃圾回收

以这个为例子:

<?php
    $a = ['one']; --- zval_a(将$a对应的zval,命名为zval_a)
    $a[] = &$a; --- step1
    unset($a);  --- step2

在 unset 之前,step1 会根据算法计算,对这个数组中所有元素进行 refcount -1 的操作,由于索引 1 对应的是 zval_a ,所以 -1 后 refcount 变为了 1。说明不是垃圾。 当执行 unset 后(step2),继续进行算法计算,由于环形引用,会得到上面的垃圾,zval_a 的 refcounnt 是 1,当对所有元素进行 -1 时,zval_a 的值会变为 0,则就会被认为是垃圾。

参考: 一看就懂系列之 由浅入深聊一聊php的垃圾回收机制 官方文档 PHP的垃圾回收机制 垃圾回收 深入理解PHP7内核之zval

Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-12-10 20:25:25

results matching ""

    No results matching ""