为什么要知道golang垃圾回收机制?

  • 优化:工作中可能涉及到需要针对垃圾回收进行优化,所以我们要知其然,才好进行这一块的优化
  • 思路:垃圾回收其实也是一种解决问题的思路,了解这种思路可以解决遇到类似的问题
  • 面试:面试,这个就不多说了

golang的垃圾回收历史进程

golang v1.3 :标记清除进行垃圾回收

  • 为什么选择标记清除?
    • 对比:为什么没有选择引用计数,标记清除对比引用计数可以避免循环引用的问题(对比-引用计数)
    • 对比:为什么没有用分代回收,因为golang 的编译器会通过逃逸分析将大部分新生对象存储栈上(栈直接被回收)
    • 实现简单
  • 过程
  • 标记清除逻辑:
    • 从程序的根对象出发,对于可达的对象进行标记
    • 对未能标记的对象进行删除
    • ps:标记清除原理类似数据结构中的有向图

golang v1.5 : 三色并发标记清除进行垃圾回收

1,为什么要把标记清除优化为三色并发标记?

  • 因为可以降低stw的时间,提高效率

2,三色标记清除法示意图和流程描述

  • 第一步:所有对象标记为白色
  • 第二步:每次GC开始就从根节点开始进行遍历,把遍历到的数据放入到灰色标记表
  • 第三步:继续遍历灰色节点,把灰色对象引用的白色对象放入灰色对象,之后将灰色对象放入黑色集合
  • 第四步:重复第三步,直到灰色中无任何对象
  • 第五步:回收白色标记表中的对象

3,怎么解决stw时间过长的问题?

  • 1,stw是什么?
    • 是stop the world的缩写,可以理解为触发stw后整个程序会停止运行2,如果不启动stw会怎么样?
    • 在三色标记回收的过程中,一个白色对象被黑色对象引用了 且 该白色对象上游没有被任何灰色对象引用 ,但是我们不会再去遍历黑色对象表,导致该白色对象被错误的回收,造成对象丢失
  • 结论:在没有stw的情况下,且满足上述标红的两个条件后会导致错误的回收,导致对象丢失
  • 术语:
    • 强三色不变式:不存在黑色对象引用到白色对象的指针
    • 弱三色不变式:所有被黑色对象引用的白色对象都处于灰色保护状态
    • ps:以上两个不变式分别对应以上标红的两个条件
  • 2,如果不启动stw会怎么样?
    • 在三色标记回收的过程中,一个白色对象被黑色对象引用了该白色对象上游没有被任何灰色对象引用 ,但是我们不会再去遍历黑色对象表,导致该白色对象被错误的回收,造成对象丢失
    • 结论:在没有stw的情况下,且满足上述的两个条件后会导致错误的回收,导致对象丢失
    • 术语:
      • 强三色不变式:不存在黑色对象引用到白色对象的指针
      • 弱三色不变式:所有被黑色对象引用的白色对象都处于灰色保护状态
  • 3,怎么解决尽量让stw时间短,又保证gc可用,不会出现对象丢失的情况?
  • 解决思路:只要保证强三色不变式或者弱三色不变式中成立一个,就可以保证不会丢失对象
  • 解决办法:
    • 插入写屏障:如果黑色的 A 对象引用 白色的B对象,则B对象标记为灰色
      • 问题:由于栈特点是容量小,速度快,所以插入屏障在栈空间中不使用,而仅仅在堆空间中使用,所以可能出现栈上发生 白色对象 被 黑色对象引用 的可能
      • 解决办法:堆上三色标记清理完后,对栈启动stw(相比对堆进行stw,这里时间会很短),然后再做一遍三色标记清除
    • 删除写屏障:被删除的对象如果自身为灰色或者白色,那么被标记为灰色,则这轮不会被回收,要到下轮才可能会被回收
  • 4,总结插入写屏障和删除写屏障的短板
  • 插入写屏障:结束后需要stw来重新扫描栈,标记栈上引用的白色对象是否真的存活
  • 删除写屏障:回收精度低,会延迟一轮回收

golang v1.8 : 三色标记清除-混合写屏障

具体操作

1、GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)

2、GC期间,任何在栈上创建的新对象,均为黑色

3、被删除的对象标记为灰色。

4、被添加的对象标记为灰色。

优点:避免了re-scan,极大的减少了stw的时间

满足条件:变形的弱三色不变式

分析

  • 第一步:相当于栈上的删除写屏障:保证了不会原来被栈引用的栈对象被删除引用后,又被其他栈上对象引用,但是由于没有删除写屏障却被回收
  • 第二步:相当于栈上的插入写屏障:保证了栈上新加对象不会由于没有写入屏障,从而被删除引用的时候被错误回收
  • 第三步:满足删除写屏障
  • 第四步:满足插入写屏障

参考链接和建议

  • 参考链接
  • 建议

建议可以先扫一遍博客,然后有不懂的地方可以看下b站的视频