PHP可以自动举办内存打点,排除不需要的工具,主要利用了引用计数
在zval布局体中界说了ref_count和is_ref , ref_count是引用计数 ,标识此zval被几多个变量引用 , 为0时会被销毁
is_ref标识是否利用的 &取地点符强制引用
为了办理轮回引用内存泄露问题 , 利用同步周期接纳算法
好比当数组或工具轮回的引用自身 , unset掉数组的时候 , 当refcount-1后还大于0的 , 就会被当成疑似垃圾 , 会举办遍历 ,而且模仿的删除一次refcount-1假如是0就删除 ,假如不是0就规复
顽固垃圾的发生进程
<?php $a = "new string"; ?>
代码中,$a变量内部存储信息为
a: (refcount_gc=1, is_ref_gc=0)='new string'
当把 a 赋 值 给 另 外 一 个 变 量 的 时 候 , a赋值给别的一个变量的时候, a赋值给别的一个变量的时候,a对应的zval的refcount_gc会加1
<?php $a = "new string"; $b = $a; ?>
此时 a 和 a和 a和b变量对应的内部存储信息为, a 和 a和 a和b同时指向一个字符串"new string" ,它的refcount酿成2
a,b: (refcount_gc=2, is_ref=0)='new string'
当用unset删除$b变量时,“new string” 的refcount_gc会减1酿成1。
<?php $a = "new string"; //a: (refcount_gc=1, is_ref_gc=0)='new string' $b = $a; //a,b: (refcount_gc=2, is_ref=0)='new string' unset($b); //a: (refcount_gc=1, is_ref=0)='new string' ?>
对付普通的变量来说,这一切很正常,可是在复合范例变量(数组和工具)中,会产生较量有意思的工作:
<?php $a = array('meaning' => 'life', 'number' => 42); ?>
$a内部存储信息为:
a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42 )
数组变量自己($a)在引擎内部实际上是一个哈希表,这张表中有两个zval项 meaning和number,所以实际上那一行代码中一共生成了3个zval,这3个zval都遵循变量的引用和计数原则,用图来暗示:
下面在$a中添加一个元素,并将现有的一个元素的值赋给新的元素:
<?php $a = array('meaning' => 'life', 'number' => 42); $a['name'] = $a['meaning']; ?>
那么$a的内部存储为 , “life” 的ref_count酿成2 , 42的ref_count是1:
a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=2, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42, 'name' => (refcount=2, is_ref=0)='life' )
假如将数组的引用赋值给数组中的一个元素,有意思的工作就会产生:
<?php $a = array('one'); $a[] = &$a; ?>
这样
a
数
组
就
有
两
个
元
素
,
一
个
索
引
为
0
,
值
为
字
符
o
n
e
,
另
外
一
个
索
引
为
1
,
为
a数组就有两个元素,一个索引为0,值为字符one,别的一个索引为1,为
a数组就有两个元素,一个索引为0,值为字符one,别的一个索引为1,为a自身的引用,内部存储如下:
a: (refcount=2, is_ref=1)=array ( 0 => (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=… )
array这个zval的ref_count是2 , 是一个环形引用
这时对$a举办unset,那么
a
会
从
符
号
表
中
删
除
,
同
时
‘
a会从标记表中删除,同时`
a会从标记表中删除,同时‘a指向的zval的refcount_gc`淘汰1.
<?php $a = array('one'); $a[] = &$a; unset($a); ?>
那么问题就发生了, a 已 经 不 在 符 号 表 中 , 用 户 无 法 再 访 问 此 变 量 , 但 是 a已经不在标记表中,用户无法再会见此变量,可是 a已经不在标记表中,用户无法再会见此变量,可是a之前指向的zval的refcount_gc变为1而不是0,因此不能被接纳,从而发生内存泄露,新的GC要做的事情就是清理此类垃圾。
为了办理轮回引用内存泄露问题 , 利用同步周期接纳算法 , 这种ref_count减1后还大于0的会被作为疑似垃圾
好比当数组或工具轮回的引用自身 , unset掉数组的时候 , 当refcount-1后还大于0的 , 会举办遍历 ,而且模仿的删除一次refcount-1假如是0就删除 ,假如不是0就规复。
到此这篇关于PHP的垃圾接纳机制代码实例讲授的文章就先容到这了,更多相关PHP的垃圾接纳机制内容请搜索剧本之家以前的文章或继承欣赏下面的相关文章但愿各人今后多多支持剧本之家!
您大概感乐趣的文章: