简述下php的垃圾回收机制

简单描述:php中的变量存储在变量容器zval中(c结构体),zval中除了存储变量类型和值外,还有is_ref和refcount字段。refcount表示指向变量的元素个数,is_ref表示变量是否有别名。如果一个zval的refcount增加,它将继续被使用,当然就不属于垃圾。如果refcount减少为0时,就回收该变量容器,属于正常释放,不属于垃圾。如果一个zval的refcount减少到非零时(这里包含循环引用的zval),它可能是垃圾,就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理。以此解决循环引用导致的内存泄漏问题

内存泄漏:程序运行过程中申请了内存,但是在使用完成后没有及时释放的现象

循环引用导致的内存泄漏:当数组或对象内部子元素引用其父元素,而此时如果删除其父元素,此变量容器并不会被删除,因为其子元素还在指向该变量容器,refcount > 0,但是由于没有指向该变量容器的符号,所以无法手动清除,因此会发生内存泄漏,直到该脚本执行结束

$a = array( 'one' );
$a[] = &$a;
unset($a);

垃圾回收算法:每当缓冲区存满时,PHP 会对缓冲区的所有zval遍历进行「模拟删除」,然后进行「模拟恢复」或者「真的删除」。但是PHP只会对进行模拟删除后refcount > 0 的zval进行恢复,那么没有进行恢复的也就是 refcount = 0 的就是垃圾了,进行真的删除。模拟删除简单的说,就是对此zval中的每个元素进行一次refcount减1操作,操作完成之后,如果zval的refcount=0,那么这个zval就是一个垃圾。模拟恢复相当于模拟删除的逆运算了

猜你喜欢

转载自blog.csdn.net/weixin_38230961/article/details/106232073