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