Golang 三色标记 + GC混合写屏障机制
Go v1.3之前的标记清除
流程
- 暂停程序业务逻辑, 找出 可达的对象,和可达对象。
- 开始标记,程序找出它所有可达的对象,并做上标记。
- 标记完 之后,然后开始清除未标记的对象.
- 停止暂停,让程序继续跑。然后循环重复这个过程,直到process程序 命周期结束。
缺点
- STW,stop the world;让程序暂停,程序出现卡顿 (重要问题)。
- 标记需要扫描整个heap
- 清除数据会产生heap碎片
- 将第四步和第三步换位置,缩短STW的范围
Go v1.5三色标记法
流程
-
只要是新创建的对象,默认的颜 都是标记为“白色”
-
每次GC回收开始, 然后从根节点开始遍历所有对象,把遍历到的对象从白色集合放 “灰 ”集合。
-
遍历灰色集合,将灰色对象引入的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
-
重复第三步, 直到灰色中无任何对象.
-
回收所有的白色标记表的对象. 也就是回收垃圾.
只使用三色标记法
- 一个白色对象被黑色对象引用(黑色对象之后的不会再去判断)
- 灰色对象与它之间的可达关系的白色对象遭到破坏
两个条件同时满足,那么会出现对象丢失的现象
强弱三色不变式
- 强三色不变式:强制性的不允许黑色对象引用白色对象
- 弱三色不变式:黑色对象可以引用白色对象,白色对象存在其他灰色对象对它的引用,或者可达它的链路上游存在灰色对象
- 如果三色标记满足强弱不变式之一,即可保证不丢失对象
屏障机制
插入屏障
对象被引用时触发的机制
- 具体操作: 在A对象引用B对象的时候,B对象被标记为灰 。(将B挂在A下游,B必须被标记为灰 )
- 满 : 强三色不变式. (不存在黑色对象引用白色对象的情况 , 因为白色会强制变成灰 )
不足:结束时需要STW来重新扫描栈, 约需要10~100ms
删除屏障
对象被删除时触发的机制
- 具体操作: 被删除的对象,如果自身为灰色或者白色 ,那么被标记为灰 。
- 满 : 弱三色不变式. (保护灰色对象到白色对象的路径不会断)
不足:
- 回收精度低,一个对象即使被删除 最后 个指向它的指针也依旧可以活过这一轮, 在下一轮GC中被清理掉。
Go v1.8混合写屏障机制
具体操作
- GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描, 需STW)
- GC期间,任何在栈上创建的新对象,均为黑色。
- 被删除的对象标记为灰色。
- 被添加的对象标记为灰色。
满足:变形的弱三色不变式. (结合了插入、删除写屏障两者的优点)
总结:
- Go V1.3 普通的标记清除法, 整体过程需要STW,效率极低
- Go V1.5 三色标记法, 对空间启动写屏障,栈空间 启动, 全部扫描之后,需要重新扫描 次栈(需要STW), 效率普通
- Go V1.8 三色标记法,混合写屏障机制, 栈空间不启动,堆空间启动, 整体过程几乎不需要STW, 效率较 高