php的gc回收机制,php垃圾回收机制相关(GC)

一直对php的垃圾回收机制不明不白,看一次记录下。

首先,说到垃圾回收,得先知道什么情况下才能产生垃圾。

正常标量类型的变量,建立出来后产生的变量容器是放到一个统一的大环境下的,但是array和object这种,比如数组的$a[1] = &$a,这种,他们的子类产生的变量容器是存放在这个数组$a自己维护的一个环境     下 的,这个时候如果unset($a)之后, 这个is_ref字段还会是1,然后refcount也会是1。(refcount=1, is_ref=1)=array (

0 => (refcount=1, is_ref=0)=‘one‘,

1 => (refcount=1, is_ref=1)=... #...的意思是指向了递归操作了,指向了原本的数组$a

)尽管不再有任何符号指向$a产生的变量容器,因为unset掉了,但是$a之前自己环境里边还在用这个变量容器,所以垃圾就这么产生了,回收不掉。因为没有别的符号指向他了,没办法再unset($a[1])了。

这种造成的内存泄漏吧,平常php脚本执行完毕也就自己关了,但是难免有人用php写一些守护进程很长时间不关闭的程序,就会造成大量内存泄漏。

其次,垃圾怎么被回收,就像刚才说的,如果一个引用计数增加,它将继续被使用,当然就不再在垃圾中。如果引用计数减少到零,所在变量容器将被清除,也不存在垃圾的概念,也就是说,只有引用计数减少

到非0值时,才会产生垃圾周期。在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾。

为避免不得不检查所有引用计数可能减少的垃圾周期,这个算法把所有可能根(possible roots 都是zval变量容器),放在根缓冲区(root buffer)中(用紫色来标记,称为疑似垃圾),这样可以同时确保

每个可能的垃圾根(possible garbage root)在缓冲区中只出现一次。仅仅在根缓冲区满了时,才对缓冲区内部所有不同的变量容器执行垃圾回收操作。

模拟删除每个紫色变量。模拟删除时可能将不是紫色的普通变量引用数减"1",如果某个普通变量引用计数变成0了,就对这个普通变量再做一次模拟删除。每个变量只能被模拟删除一次,模拟删除后标记为灰。

模拟恢复每个紫色变量。恢复是有条件的,当变量的引用计数大于0时才对其做模拟恢复。同样每个变量只能恢复一次,恢复后标记为黑,基本就是第二步的逆运算。这样剩下的一堆没能恢复的就是该删除的蓝色节点了,然后真正的遍历出来删除掉。

算法中都是模拟删除、模拟恢复、真的删除,都使用简单的遍历即可(最典型的深搜遍历)。复杂度为执行模拟操作的节点数正相关,不只是紫色的那些疑似垃圾变量。

原文:https://www.cnblogs.com/camouflage/p/10981086.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值