Stay Hungry.Stay Foolish.
PHP内核GC解决循环引用问题

文章分析的是PHP内核解决循环引用问题的方式,另外JVM使用的是一种叫可达性分析的算法(从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。),两种方法有异曲同工之妙。

内存泄露例子

先看下面这样一段代码

<?php
$a = array('one');
$a[] = &$a;
unset($a);
?>

如果使用最原始的引用计数,$a这个结构的refcount是2, 使用unset之后refcount-1, 但是代码已经没有变量指向这个结构了,也就是说我们无法访问到array(‘one’), 但是这个结构依然占用着内存, 所以即便此刻我们拥有手动释放内存的能力,也无法去释放这块“野内存“, 出现了内存泄露。

PHP内核解决手段

我们来看看php5.3新的zend引擎是如何解决这种情况下的内存泄露。

  1. 内核先收集哪些属于垃圾,如果一个变量refcount-1操作之后等于0, 那么这只是个普通的垃圾,简单粗暴直接释放内存,如果不等于0,那么内核就会认为这个有可能是要认真对待的垃圾,会被放入一个叫root buffer的容器。
  2. 当root buffer满了之后,默认是10000, 就会启用一次GC扫描,对每一个zval结构内部的元素进行refcount-1操作,如果最后这个zval的refcount=0,那么这个zval就被标记为垃圾,说明这个zval结构没有被外部元素引用。
  3. 对zval结构的元素进行refcount+1逆操作,释放被标记垃圾的zval结构内存。

优点: 可以解决循环引用导致的内存泄露问题。 缺点: 在root buffer满了的时候会启用GC扫描,性能会有一定的损失,但是可以接受。

PHP
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
评论

暂无评论~~