嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

周梦康 发表于 2016-02-25 8467 次浏览 标签 : php

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

什么是垃圾

GC(Garbage Collection)负责清理的垃圾是指:当变量被删除之后,该变量原来连接的容器zval还存在,导致现在又没有任何变量名指向该zval。此时该zval就是需要被回收的垃圾。

什么时候会造成这个情况,可以先了解 PHP 内存泄漏

生成垃圾

下面配合官方 PHP 垃圾回收 中的配图进行说明。官方文档中的图可能不仔细分析会觉得很难懂,下面我配以一段代码进行说明

$a = "one";
$b = array($a);
$b[] = &$b;

xdebug_debug_zval('a');
xdebug_debug_zval('b');

打印的结果

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)=..., 
	    )

用图表示

PHP 垃圾回收

这时候unset($b)就会出现如下情况

这时候原来$b指向的zval容器(假设命名为zval_b)的连接断开了,就导致了内存泄漏,而$a所指向的zval容器的连接还存在。zval_b也就是我们所说的垃圾。那么GC 如何将其识别出来呢?

垃圾回收的实现

1. 上面的zval_b被视为可能的垃圾存放到根缓存区。

2. 算法会对每个节点(初始节点本身不做减1操作)所包含的zval进行refcount模拟减1操作,现在对zval_b这个容器里的所有节点进行操作,首先对[0]号元素的节点进行模拟减1操作,然后对[1]号元素的节点模拟进行减1操作。只是模拟并不是真正的减1。

3. 算法会对每个节点(初始节点本身不做操作)所包含的refcount > 0zval进行refcount加1操作,现在对zval_b这个容器进行操作,[0]号元素的refcount = 0所以不予以处理,然后对[1]号元素的节点进行加1操作。如此,就确定了垃圾部分,将其标记,同时也对非垃圾进行了还原。

4. 遍历zval_b节点,将上步中标记成垃圾的节点zval释放掉。

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表