Golang中的GC机制

参考:https://www.bilibili.com/video/BV1wz4y1y7Kd?spm_id_from=444.41.0.0

Go V1.3之前 标记清除(mark and sweep)

步骤:

第一步,暂停程序业务逻辑,找出可达和不可达的对象。
第二步,开始标记,程序找出它所有可达的对象,并做上标记。
第三步,标记完之后,清除未标记的对象。
第四步,停止暂停,让程序继续执行。
标记清除的缺点
  1. STW, stop the world,让程序暂停,程序出现卡顿(严重)
  2. 标记需要扫描整个heap
  3. 清除数据会产生heap碎片

Go V1.5 三色标记法

三色:白灰黑
程序起初创建,全部标记为白色,将所有对象放入白色集合中。
遍历Root Set(非递归形式,只遍历一次),得到灰色节点。
遍历灰色标记表,将可达的对象,从白色标记为灰色,遍历之后的灰色标记为黑色。
重复上一步,直到灰色标记表中无任何对象。

Go V1.8 混合写屏障机制

三色标记最不希望看到:1.一个白色对象被黑色对象引用,2.灰色对象与的白色对象之间的可达关系遭到破坏。
以上两条同时发生时,没有STW就会出现对象丢失现象。
最简单的解决方式就是STW,但是STW的过程有明显的资源浪费,对所有的用户程序都有很大的影响。
故为了保证对象不丢失的情况下尽可能的提高GC效率,可以想办法使两种情况不会同时发生。
强三色不变式: 强制性的不允许黑色对象引用白色对象(破坏1.一个白色对象被黑色对象引用)
弱三色不变式: 黑色对象可以引用白色对象,白色对象存在其他的灰色对象对它的引用,或者可达它的链路上游存在灰色对象(破坏2.灰色对象与的白色对象之间的可达关系遭到破坏)

插入屏障:

具体操作: 在A对象引用B对象的时候,B对象被标记为灰色。
满足:强三色不变式。
不足:结束时需要STW来重新扫描栈。

删除写屏障:

具体操作: 被删除的对象,如果自身为灰色或者白色,那么被标记为灰色。
满足:弱三色不变式。
不足:回收精度低,一个对象即使被删除了最后一个指向它的指针依旧可以活过这一轮,在下一轮中才被GC清理。

Go V1.8的三色标记法+混合写屏障机制:

具体操作:
1. GC开始栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)。
2.GC期间,任何在栈上创建的新对象,均为黑色。
3.被删除的对象标记为灰色。
4.被添加的对象标记为灰色。
满足:变形的弱三色不变式(结合了插入、删除写屏障两者的优点)。
posted @ 2022-02-19 14:29  sqdtss  阅读(204)  评论(0编辑  收藏  举报