Go的GC垃圾回收机制
历史原因
- go发展史上采用过的一些方法
-
go 1.3之前使用标记清除 (mark and sweep) -
go 1.5三色标记法 -
go 1.8三色标记法 + 混合写屏障机制
- 垃圾回收设计的名词
- 自动释放
- 垃圾回收
- 三色标记法
- 内存管理
- STW(stop the world) 全部停止执行
标记清除法
标记清除法过程
- 暂停程序业务逻辑
暂停程序,绘制程序和对象的可达关系。这里的对象是个广义的概念,包括对象和变量或方法

- 找到所有的可达对象,并做上标记。

3. 清除未标记对象

- 停止暂停
停止暂停,让程序继续跑,然后循环重复这个过程,直到程序生命周期结束。
标记清除的缺点
-
STW(stop the world):让程序暂停,程序出现卡顿,影响性能(核心问题)
-
标记需要扫描整个
heap(堆) -
清除数据会产生
heap碎片 -
可以对以上方法进行改进(如下图),缩短
STW的返回,但是还是会很大。

三色标记法的流程
三色标记法中,要切记,灰色只是一种状态,我们进行遍历最后的结果,就是没有灰色节点。
创建程序
- 程序创建的时候,默认所有的对象都是白色。只要是新创建的对象,默认颜色就是白色

2. 遍历对象(非递归调用,只遍历一次),得到灰色节点

切记这里的遍历,是从根节点出发。遍历到 对象1 和 对象4,切记 只遍历这一步,二不是递归调用。,他会把遍历到的 对象1 和 对象4加入到灰色标记表中
- 遍历灰色集合
对灰色节点进行遍历,把灰色几点能达到的点,标记为灰色节点,把自己标记为黑色节点。

重复遍历灰色标记表,直到不存在灰色节点。

灰色标记表只是一种中间状态,最终我们要把灰色标记表中的东西全部清理掉。只剩下要么都是白的,要么都是黑的
- 回收白色垃圾

三色标记法不使用 STW 会出现的问题
说白了,他的问题就在于黑色节点引用白色节点了,这个白色节点,如果不停留,就会被删除掉。


综上所述,三色标记法最不希望发生的事
- 一个白色对象被黑色对象引用
- 灰色对象同时又丢了对该白色对象的引用
如果以上两个条件同时满足,那么就会出现对象丢失现象
强弱三色不变式
-
强三色不变式: 强制性的不允许黑色对象引用白色对象 :破坏了
条件一

-
弱三色不变式: 黑色对象可以引用白色对象,但是要求白色对象的链路上游,存在灰色对象 :破坏了条件二

只要满足了强三色不变式或者弱三色不变式其中任何一个条件,就可以保证对象不丢失。那么如何保证呢?就要借助于屏障机制。
屏障机制
什么是屏障
屏障就是相当于在正常的流程中,插入了一道工序,在某些个语言里,屏障也叫做 回调,Hook 或者 handler、钩子函数。

插入屏障和删除屏障
屏障机制在 go 语言里,分为两种,分别为 插入屏障 和 删除屏障,由名字可知
- 插入屏障: 当一个对象被引用时,触发的机制
- 删除屏障: 一个对象被删除的时候,触发的机制
插入屏障
具体操作: 在 A 对象引用 B 对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须标记为灰色)
这样可以满足强三色不变式,因为不存在黑色对象引用白色对象的情况了,因为白色会被强制编程灰色。

插入屏障的问题
因为每次引用对象,都触发 插入屏障 的话,会影响性能;堆栈两种结构相比,栈对性能的要求更高,所以为了不影响 栈 上的性能,是不执行插入屏障的,只有在 堆 上才执行插入屏障。
那么栈是如何进行垃圾回收的呢?

栈是在 堆 上的数据都扫描完了以后,然后启动 STW,再重新扫描一遍,标记完以后,进行删除。
删除屏障
被删除的对象,如果自身是灰色或者白色,那么就会被标记为灰色(其实就是为了保护灰色的一轮)
满足: 弱三色不变式。(保护灰色对象到白色对象的路径不会断)
- 要删除对象2

- 把
对象2删除以后,要把对象2变成灰色

- 接下来,把所有的白色对象删除掉。

从上边可以看出来,这样回收删不干净,部分节点要等第二轮CG才能删除
混合屏障
单独使用删除写屏障和插入写屏障存在的问题
插入写屏障的不足: 结束时,需要STW来重新扫描栈,大概需要 10~100ms
删除写屏障的不足:回收精度低,一个对象即使被删除了,最后一个指向它的指针,也依旧可以活过这一轮,
三色标记 + 混合写屏障
GC开始,优先扫描栈,将栈上的可达对象全部扫描,并标记为黑色(之后不再进行第二次扫描,无需STW)。GC期间,在栈上创建的节点,也都是黑色。- 被删除对象,标记为
灰色 - 被添加的节点,也标记为
灰色
注意,为保证栈的性能,栈是不引入屏障机制的。删除对象就是添加一个nil对象,所以删除也叫删除写屏障。

参考文献
https://www.bilibili.com/video/BV1wz4y1y7Kd?share_source=copy_web
浙公网安备 33010602011771号