Golang中每个版本的GC机制都一样吗

1.3版本

1.3版本之前使用的是标记清除法:在gc开启时会开启STW,停止程序的运行,从根节点出发,标记所有可达对象,然后停止STW,回收所有未被标记的对象。这个方法的弊端是在整个GC期间需要STW,将整个程序暂停,大大降低了性能。

1.5版本

1.5版本使用的是三色标记法+插入写屏障/删除写屏障,默认是使用插入写屏障

三色标记法的工作原理

在初始时,所有对象都会被标记成白色,gc开始之后,会从根节点开始遍历,将可直达的对象标记为灰色,然后再将灰色可直达的对象标记为灰色,将自己标记为黑色,一直重复这个步骤,直到标记完所有对象,把标记为白色的对象当作垃圾回收掉。

但是对三色标记法来讲,仍然需要依赖STW的. 因为如果不暂停程序, 程序的逻辑改变对象引用关系, 这种动作如果在标记阶段做了修改,会影响标记结果的正确性。

三色标记法的过程中对象丢失,需要同时满足下面两个条件:

  • 条件一:白色对象被黑色对象引用

  • 条件二:灰色对象与白色对象之间的可达关系遭到破坏

只要把上面两个条件破坏掉一个,就可以保证对象不丢失,所以就提出了两种破坏条件的方式:强三色不变式弱三色不变式

强三色不变式

规则:不允许黑色对象引用白色对象

破坏了条件一: 白色对象被黑色对象引用

弱三色不变式

规则:黑色对象可以引用白色对象,但是白色对象的上游必须存在灰色对象

破坏了条件二:灰色对象与白色对象之间的可达关系遭到破坏

插入写屏障:

规则:当一个对象引用另外一个对象时,将另外一个对象标记为灰色

满足:强三色不变式。不会存在黑色对象引用白色对象

仅会在堆内存中生效不对栈内存空间生效,这是因为go在并发运行时,大部分的操作都发生在栈上,函数调用会非常频繁。数十万goroutine的栈都进行屏障保护自然会有性能问题

插入写屏障最大的弊端就是,在一次正常的三色标记流程结束后,需要对栈上重新进行一次stw,然后再rescan一次。

删除写屏障

规则:在删除引用时,如果被删除引用的对象自身为灰色或者白色,那么被标记为灰色。

满足弱三色不变式。灰色对象到白色对象的路径不会断

引入删除写屏障,有一个弊端,就是一个对象的引用被删除后,即使没有其他存活的对象引用它,它仍然会活到下一轮。如此一来,会产生很多的冗余扫描成本,且降低了回收精度

对比插入写屏障和删除写屏障
  • 插入写屏障:

    • 插入写屏障哪里都好,就是栈上的操作管不到,所以最后需要对栈空间进行stw保护,然后rescan保证引用的白色对象存活。

  • 删除写屏障:

    • 在GC开始时,会扫描记录整个栈做快照,从而在删除操作时,可以拦截操作,将白色对象置为灰色对象。

    • 回收精度低。

1.8版本

1.8版本后使用的是三色标记法+混合写屏障

混合屏障机制的核心定义
  • GC刚开始的时候,会将栈上的可达对象全部标记为黑色

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

  • 堆上被删除的对象标记为灰色

  • 堆上新添加的对象标记为灰色

屏障限制只在堆内存中生效。避免了最后节点对栈进行STW的问题,提升了GC效率

1.9版本

1.9版本写屏障又进行了进一步优化

在Go1.9之前,很多库函数都是会触发stop-the-world的,而现在只会触发并发的垃圾回收。比如:runtime.GC,debug.SetGCPerent and debug.FreeOSMemory,现在只会触发并发的垃圾回收,只会阻塞当前正在调用的goroutine,直到gc完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萝卜说菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值