Ruby 2.2 的增量垃圾收集机制(2)

为了使这一过程是增量的,我们必须让 (3)是增量的。 我们这样来做,选择一些灰色类并将他人的引用标记为灰色,然后返回 Ruby 执行过程,再继续增量标记,不断重复这一过程。 

Ruby 2.2 的增量垃圾收集机制

图:普通标记 (STW: 停止整个应用) vs. 增量标记

增量标记存在一个问题。在 Ruby 执行过程中黑色类会引用白色类。引起该问题的原因是我们把黑色类定义为没有引用白色类的类。为了阻止这种情况,我们需要"write-barrier“,在创建过程中发现引用白色类的黑色类。

假如,一个数组对象已经被标记为”黑色“。

ary = []
# GC runs, it is marked black

现在,创建一个新对象 object obj = Object.new 是白色的,如果我们运行以下代码

现在一个黑色类指向了一个白色类。如果没有灰色类指向 obj,obj 在标记阶段结束时是白色,这将产生一个错误。清理时会产生重大 bug,我们要避免这个错误。

一个类指向一个新类时,write-barrier 将被调用。write-barrier 会检测到一个黑色类指向了一个白色类。当该事件发生时,黑色类将被标记为灰色(或者将白色类标记为灰色),write-barrier 彻底解决了GC 的这人灾难性 bug。

如你所见,增量 GC 算法的基本思路并不困难,或许你会问:“为什么 Ruby 还没有使用这种简单的 GC 算法”。

Ruby 2.2 的增量 GC

在 Ruby 解释器里实现增量标记有一个大问题。 (CRuby):缺少write-barriers。Ruby 没有足够的write-barriers。 

在 2.1 上实现的分代 GC 也需要write-barriers。为了引入分代 GC,我们发明了一种新技术叫做”write barrier unprotected objects“。这意味着我们将所有类分成“write barrier protected objects”(保护类)和”write barrier protecte objects“(非保护类)我们可以保障所有保护类的引用都是被管理的。我们不能控制非保护类的引用。引用”非保护类“我们可以为 Ruby2.1 实现分代 GC。

使用非保护类,我们也可以做增量GC:

(1)将所有活动对象置为白色。
(2)将确定活动的类置为灰色,包括栈里的类。
(3)选择一个灰色类,访问类的每一个引用,并置为灰色。将我们最初选择的类置为黑色。
重复以上过程,直到没有灰色类,只剩下白色类和黑色类。这一步是增量实现。
(4)将可以指向白色的非保护类置为黑色,这样所有非保护的黑色类只需一次扫描。
(5)收集所有白色类,因为所有活动类已经被置为黑色。
引入(4)可以保证没有非活动的白色类。

Ruby 2.2 的增量垃圾收集机制

图:在标记结束时重新扫描写屏障的非保护类。

不幸的是引入步骤(4)会引起我们希望避免的长中断次数。
中断时间和写屏障的非保护类的数量有关。在Ruby语言中,大部分对象是String,Array,Hash和用户定义类,它们都是有写屏障的保护类。所有写屏障非保护类引起的长中断在大多实际运行中并不会产生什么问题。

我们只在major GC引入了增量标记,因为没有抱怨minor GC的中断时间。增量垃圾收集器的最大中断时间要小于minor GC的中断时间。如果你在minior GC不存在中断时间问题,就不用担心major GC的中断时间。

我还介绍过为Ruby实现增量垃圾收集器的一人小技巧。我们得到一系列“黑色非保护”类。为了快速执行垃圾清理,我们准备了一个非保护的bitmap代表非保护类,一个独立的已标记bitmap代表已标记类。使用两个bitmaps的逻辑可以获取“黑色非保护”类。

增量垃圾收集器中断时间评测

为了计量垃圾收集器产生在的中断时间,让我们使用 gc_tracergem. gc_tracer gem引用了 GC::Tracer模块在垃圾收集事件中获取相关参数。gc_tracergem将每个参数都保存在文件中。

垃圾收集事件包括以下事件:

开始

标记结束

清理结束

创建对象

释放对象

进入

离开 

如我前面所解释,Ruby的垃圾收集包含两个阶段:“标记附件”和“清理”阶段。“开始“是”开始标记附件“事件,”标记结束“是”标记附件结束“事件,”标记结束“也现时意味着”开始清理阶段",当然“清理结束”代表”清理阶段“结束,也意味着垃圾清理过程的结束。

”创建对象“和”释放对象”很容易理解:对象分配和对象释放事件。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/db34a274cedad14083732a0082cc5922.html