首页 > 作文

PHP的垃圾回收机制之引用计数

更新时间:2023-04-07 17:25:53 阅读: 评论:0

1,介绍

php的垃圾回收机制(gc)是在php5之后出现的,而在php5.3版本之前使用的都是“引用计数”的方式。实现引用计数的实质就是在每个内存对象中都有一个计数器,当内存对象被变量引用时,计数器+1,当变量取消或更改引用内存时,计数器-1,直到计数器中的值为0时,说明该内存对象没有被变量引用,,就产生了一个无意义的内存对象。php就会销毁释放内存,进行垃圾回收。

2,实现

每个变量被赋值时就会生成叫‘zval’的变量容器,‘zavl’容器中除了包含变量名,量的类型和变量的值以外,还包含两个字节的额外信息。第一个是”is_ref”,是个布尔值,用来表示该变量是否被引用,php就是根据这个判断变量是否是普通类型还是引用类型;另一个是‘refcount’,功能类似于计数器,记录指向该变量容器的变量个数。

1,生成并显示一个新的zval容器

$a;xdebug_debug_zval('a');//a: no such symbo
$b="new string";xdebug_debug_zval('b');//b: (refcount=1, is_ref=0),

可以看到芭蕾男孩:变量赋值后生成的‘zavl’容器中的参数。其中refcount=1表示一个变量指向该变量容器。

2,添加一个‘zavl’的引用计数

$b="new string";xdebug_debug_zval('b');$c=$b;xdebug_debug_zval('b');//b: (refcount=2, is_ref=0),string 'new string' (length=10)
$d="new string";
xdebug_debug_zval('d');//d: (refcount=1, is_ref=0),

这时,引用次数是2,因为同一个变量容器被变量b和变量c关联。当将一个变量赋值给另一个变量时,php不会去复制已生成的变量容器。而将一个值赋值给一个变量时,会重新生成一个新的‘zavl’容器。

3,清空并删除一个引用计数

$b="new string";$c=$b;unt($b);xdebug_debug_zval('c');//c:(refcount=1, is_ref=0),string 'new string' (length=10)
unt($c);xdebug_debug_zval('c');//c: no such symbol

当手无寸铁猜一字任何关联到某个变量容器的变量离开它的作用域(比如:函数执行结束),或者对变量调用了函数 unt()时,”refcount“就会减1。当refcount=0时,包含类型和值的这个中国闭关锁国变量容器就会从内存中删除。

上面的数据类型都是标量数据类型,而复合数据类型(array,object)又有不同。

4,生成一个复合数据的变量容器

$arr=[];xdebug_debug_zval('arr');$array=['name'=>'张三','age'=>'18'];xdebug_debug_zval('array');

结果如下:

图示:

可以看到:数组分配了三个zval容器:array name age

5,添加一个已经存在的元素到数组中

$array = [    'name' => '张三',    'age' => '18'];$array['zhangsan'] = $array['name'];xdebug_debug_zval('array');

6,销毁包含数组名信息的’zavl’变量容器

$array = [    'name' => '张三',    'age' => '18'];$array['zhangsan'] = $array['name'];unt($array);xdebug_debug_zval('array');

其结果如下

删除数组中的一个元素,就是类似于从作用域中删除一个变量. 删除后,数组中的这个元素所在的容器的“refcount”值减少,同样,当“refcount”为0时,这个变量容器就从内存中被删除。

一般来说,‘zavl’容器中的refcount=0时,该变量容器就是垃圾,会被php引擎销毁。但是有一种情况:’zavl’容器中的refcount不为0,却没有变量指向它,仍然是个垃圾。

环状引用就是一个例子,即把数组作为一个元素添加到自己。

7,生成一个包含环状引用的‘zavl’容器

$arr = [    'name' => '张三'];$arr[] = &$arr;xdebug_debug_zval('arr');

结果如下

图示:

8,删除环状引用

$arr = [   '张三'];$arr[] = &$arr;unt($arr);xdebug_debug_zval('arr');

图示:

现在,虽然没有任何变量指向该‘zavl’,但由于数组元素“0”仍然指向数组本身,所以该‘zavl’不能被清除 。而又因为没有另外的变量指向它,用户没有办法清除这个结构,结果就会导致内存泄漏。庆幸的是,php脚本运行完毕后会清除这个数据结构。但是在php清除之前,将耗费不少空间的内存。而在一般情况下,php脚本运行完毕因此环状引用内存泄露的问题一般只影响长时间运行的程序脚本。并且在5.3版本后垃圾处理虽然其基础仍然是引用计数,但是做了一些改良,能够将环状引用导致的内高一随笔存泄露控制在一定的规模以内。

当然,我们也可以手动的清除环状结构

9,手动清除环状引用

$arr = [   '张三'];电容计算公式$arr[] = &$arr;$arr = null;xdebug_debug_zval('arr');unt($arr);xdebug_debug_zval('arr');

结果如下

$arr=null后,虽然变量容器‘zavl’还存在,但是之前储存在内存中引用传递的值却是完全删除掉了,最后再使用unt($arr)就可以断开变量名arr和null值之间的联系,令refcount=0就能够释放到内存了。

本文发布于:2023-04-07 17:25:51,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/5ba6693b6fb19bf7015d5020b1f4855f.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:PHP的垃圾回收机制之引用计数.doc

本文 PDF 下载地址:PHP的垃圾回收机制之引用计数.pdf

下一篇:返回列表
标签:变量   容器   环状   内存
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图