三色标记法和混合写屏障

目录

一、Go垃圾回收发展历史

1.3之前:原始的标记清除算法(mark and sweep)

1.3 减少STW暂停的时间范围

1.5 三色并发标记

1.8 混合写屏障(hybrid write barrier)机制

二、三色并发标记法

1.三色标记流程

2.三色标记不启动STW的问题

三. 屏障机制

(1) “强-弱” 三色不变式

(2) 插入写屏障

(3)  删除写屏障

(4)  混合写屏障机制

1. 混合写屏障规则

2. 混合写屏障的具体场景


一、Go垃圾回收发展历史

1.3之前:原始的标记清除算法(mark and sweep)

1.3 减少STW暂停的时间范围

1.5 三色并发标记

1.8 混合写屏障(hybrid write barrier)机制


二、三色并发标记法

1.三色标记流程

1)全部对象,放入白色集合

2)遍历root对象,从白色集合移入灰色集合

3)遍历灰色集合,将灰色对象引用的对象从白色集合移入灰色集合,然后将原灰色对象移入黑色集合

4)重复第3步,知道灰色集合中没有灰色对象

5)回收所有白色对象

2.三色标记不启动STW的问题

如上的三色标记,如果不启动STW,并发的垃圾回收,仍然会出现问题;

会造成对象丢失的情形:

条件1:  一个白色对象被黑色对象引用(黑色已遍历过,不会再次遍历)

条件2: 该白色对象没有被灰色引用,或灰色引用被破坏(灰色同时丢了该白色对象)

1)已经标记为灰色对象的2,有p指针指向白色对象3;

2)已经标记为黑色对象的4,新建一个指向白色对象3的指针q,并移除指针p

3)对象4已经被标记为黑色对象,不会再被重新扫描,对象3会一直在白色集合

4)对象3被引用着,却被回收了


三. 屏障机制

(1) “强-弱” 三色不变式

GC回收器对象不丢失的两种方式:.

强三色不变式:不存在黑色对象引用到白色对象的指针(破坏条件一)。

弱三色不变式:所有被黑色对象引用的白色对象都处于灰色保护状态(破坏条件二)。

(2) 插入写屏障

对象被引用时,触发的屏障(屏障,相当于拦截器,额外操作);

具体操作: 在A对象引用B对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须被标记为灰色);

满足方式: 强三色不变式

栈空间的特点是容量小,但是要求响应速度快,因为函数调用弹出频繁使用;

所以“插入写屏障”机制,在栈空间的对象操作中不使用(启动STW,重新标记),而仅仅使用在堆空间使用;

程序开始,对象全部标记为白色;

根节点Root对象,放入灰色集合;

遍历灰色集合,灰色集合引用的对象变为灰色,原对象变为黑色;

对象1下游添加对象9,对象4下游添加对象8;

对象8挂在黑色4下,变为灰色(堆内存,强三色);对象9保持白色(栈内存);

继续遍历灰色集合,知道灰色集合中没有对象;

栈内存仍然有白色对象被引用,需要对栈内存重新标记(启动STW,防止再次被干扰)

 

最后,回收剩余白色对象;

(3)  删除写屏障

具体操作: 被删除的对象,如果自身为灰色或者白色,那么被标记为灰色。

满足: 弱三色不变式. (保护灰色对象到白色对象的路径不会断)

 

 

 

这种方式的回收精度低,一个对象即使被删除了最后一个指向它的指针,也依旧可以活过这一轮,在下一轮GC中被清理掉。

(4)  混合写屏障机制

插入写屏障和删除写屏障的缺点:

插入写屏障:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活;

删除写屏障:回收精度低,GC开始时STW扫描堆栈来记录初始快照,这个过程会保护开始时刻的所有存活对象;

1. 混合写屏障规则

具体操作:

1)GC开始将栈上的对象全部引用扫描并标记为黑色 (之后不再进行第二次重复扫描,无需STW)。

2)GC期间,任何在栈上创建的新对象,均为黑色(保证栈全为黑色对象)。

3)被删除的对象标记为灰色(插入写屏障)。

4)被添加的对象标记为灰色(删除写屏障)。

满足: 变形的弱三色不变式

2. 混合写屏障的具体场景

1)GC开始,全部对象都为白色

2)扫描栈对象,全部标记为黑色


版权声明:本文为weixin_35655661原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。