go 高阶 の GC垃圾回收机制



一.历史原因

go发展史上采用过的一些方法

  • go 1.3 之前使用标记清除
  • go 1.5 三色标记法
  • go 1.8 三色标记法 + 混合写屏障机制

垃圾回收设计的名词

  • 自动释放
  • 垃圾回收
  • 三色标记法
  • 内存管理
  • SWT(stop the world) 全部停止执行



v1.3 之前的标记 - 清除方法

暂停程序业务逻辑,找出不可达的对象,和可达对象。

在这里插入图片描述
找到所有的可达对象,并做上标记。
在这里插入图片描述
标记完成以后,开始清楚未标记的对象
在这里插入图片描述
停止暂停,让程序继续跑,然后循环重复这个过程,直到 process 程序生命周期结束。



标记清除的缺点

  • STW:让程序暂停,程序出现卡顿(重要问题)
  • 标记需要扫描整个 heap
  • 清除数据会产生 heap 碎片
  • 将第三步和第四步调换位置,缩短 STW 的返回,但是还是会很大。


二.三色标记法

三色标记法的流程

只要是新创建的对象,默认颜色就是白色

在这里插入图片描述
第二步,每次 GC 回收开始,然后从根节点开始遍历所有对象,把遍历到的对象,从白色集合放入灰色集合
在这里插入图片描述
遍历灰色集合,将灰色对象的引用对象,从白色集合放入灰色集合,之后会将此灰色对象放入到黑色集合。
在这里插入图片描述
遍历上边的步骤,直到灰色节点里没有东西。
在这里插入图片描述


如果三色标记法不使用 STW 会出现的问题

在这里插入图片描述
如果三色标记法不被 STW 保护

  1. 一个白色对象被黑色对象引用
  2. 灰色对象与它之间的可达关系的白色对象遭到破坏
  3. 如果两个条件同时满足,那么就会出现对象丢失的现象


强弱三色不变式

  • 强制性的不允许黑色对象引用白色对象 :破坏了条件一
  • 黑色对象可以引用白色对象,但是要求白色对象的链路上游,存在灰色对象 :破坏了条件二
    在这里插入图片描述

只要满足了强三色不变式或者弱三色不变式之一,就可以保证对象不丢失。那么如何保证呢?就要借助于屏障机制。




三.屏障机制

屏障机制有点类似于其他语言的钩子函数,可以在不影响正常主程序正常使用的情况下,做一下额外的事情。有点类似于 vue 里面的声明周期函数

屏障机制
插入屏障
删除屏障
  • 插入屏障: 对象被引用时触发的机制
  • 删除屏障: 对象被删除时,触发的机制

插入屏障

具体操作: 将 B 挂载到 A 下游,B 必须被标记为灰色
满足了强三色不变式,不存在黑色对象引用白色对象的情况,因为白色会被强制编程灰色

注意,插入屏障,只是对 内的数据启动插入屏障,因为 的内存比较小,所以 不启动插入屏障,所以在回收白色节点之前,会对 中的数据重新扫描,并且加 STW 暂停保护栈,防止外界干扰。然后对 中的对象进行一次三色标记,直到没有灰色节点。

在这里插入图片描述

插入屏障存在的不足:
结束时,需要STW来重新扫描栈,大约需要10~100ms



删除屏障

被删除对象,如果自身为灰色或者白色,那么就被标记为灰色。
满足 弱三色不变式(保护灰色对象到白色对象的路径不会断)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

遍历灰色的标记,将可达对象,从白色标记为灰色,遍历灰色以后,就会将灰色标记黑色,

由上图可以看出,这种方法存在的问题

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

它之所以要这么做,就是为了防止在删除的时候,成为另一个对象的引用节点。



四. 三色标记法 + 混合写屏障

  1. GC 开始将栈上的可达对象全部扫描,并标记为黑色(这是一个前提,之后不再进行第二次重复扫描,无需 STW
  2. GC 期间,在栈上创建的新对象,均为黑色
  3. 被删除的对象标记为灰色
  4. 被添加的对象标记为灰色

栈不启用屏障,堆启用屏障

满足: 变形的弱三色不变式,(结合了插入、删除写屏障两者的优点)

在这里插入图片描述





四 总结

  • Go V1.3 中普通的标记清除法,整体过程需要 STW,效率极低
  • G0 V1.5 三色标记法,对空间启动写屏障,栈空间不启动,全部扫描之后,需要重新扫描一次栈(需要STW),效率普通
  • 三色标记法 + 混合写屏障机制,栈空间不启动,堆空间启动,整体过程几乎不需要 STW,效率极高。


查考文献

【1】https://www.bilibili.com/video/BV1wz4y1y7Kd?p=14&share_source=copy_web

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值