• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

php垃圾回收之回收计策和算法

php 搞代码 4年前 (2022-01-24) 19次浏览 已收录 0个评论

php垃圾回收之回收策略和算法

一、垃圾回收实现方式

? ? ?在以前的php中用到的是引用计数机制处理垃圾回收问题,但是这个机制存在一个弊端,就是无法处理循环引用引起的内存泄露。然而在php5.3.0以后的版本中(包含5.3.0)使用了专门GC机制(同步算法)清理垃圾,来处理这个内存泄露问题。下面就是介绍它是如何实现的:

? ??首先要了解几个基本的准则:

1:如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾。

2:如果一个zval的refcount减少到0,?那么zval可以被释放掉,属于垃圾。

3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾。

? ? ?只有在准则3下,GC才会把zval收集起来,然后通过新的算法来判断此zval是否为垃圾。那么如何判断这么一个变量是否为真正的垃圾呢?简单的说,就是对此zval中的每个元素进行一次refcount减1操作,操作完成之后,如果zval的refcount=0,那么这个zval就是一个垃圾。这个原理咋看起来很简单,但是又不是那么容易理解,下面通过结构图来深入理解:

? ? ?A:为了避免每次变量的refcount减少的时候都调用GC的算法进行垃圾判断,此算法会先把所有前面准则3情况下的zval节点放入一个节点(root)缓冲区(root buffer),并且将这些zval节点标记成紫色,同时算法必须确保每一个zval节点在缓冲区中之出现一次。当缓冲区被节点塞满的时候,GC才开始开始对缓冲区中的zval节点进行垃圾判断。

? ? ?B:当缓冲区满了之后,算法以深度优先对每一个节点所包含的zval进行减1操作,为了确保不会对同一个zval的refcount重复执行减1操作,*本文来@源gao@daima#com搞(%代@#码@网2

搞代gaodaima码

一旦zval的refcount减1之后会将zval标记成灰色。需要强调的是,这个步骤中,起初节点zval本身不做减1操作,但是如果节点zval中包含的zval又指向了节点zval(环形引用),那么这个时候需要对节点zval进行减1操作。

? ? ?C:算法再次以深度优先判断每一个节点包含的zval的值,如果zval的refcount等于0,那么将其标记成白色(代表垃圾),如果zval的refcount大于0,那么将对此zval以及其包含的zval进行refcount加1操作,这个是对非垃圾的还原操作,同时将这些zval的颜色变成黑色(zval的默认颜色属性)

? ? ?D:遍历zval节点,将C中标记成白色的节点zval释放掉。

二、举例详解垃圾回收过程

? ? ?通过上面的说明,大家可能已经有了一定的印象,那实际应用中是如何具体操作的呢?下面就通过例子说明:

? ? ①在刚刚声明变量并赋值的情况下,其实就相当于准则1(如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾),变量不是垃圾,也不会进行gc检查。

$a = "one";$b = array();$b[] = $a;$b[] = & $b;$c = "two";//声明了三个变量$a、$b、$c。这个时候refcount都是增加的情况,变量不是垃圾也不会放入到root缓冲器等待垃圾检查。xdebug_debug_zval( 'a' );  xdebug_debug_zval( 'b' );  xdebug_debug_zval( 'c' );  //输出分别如下:a: (refcount=2, is_ref=0)='one'b: (refcount=2, is_ref=1)=array (     0 => (refcount=2, is_ref=0)='one',     1 => (refcount=2, is_ref=1)=... )  c: (refcount=1, is_ref=0)='two'

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:php垃圾回收之回收计策和算法
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址