go

gc of go

Posted by keming on August 24, 2021

传说

  • Go语言早期的gc非常烂,批评这个语言的火力90%都给了gc:“实习生写出来的。”
  • 后期经过不断优化,go的gc已经非常优秀了,实时性极佳。

文章

  • 于是我左看右看,找到了一篇细致的文章:https://zhuanlan.zhihu.com/p/334999060

总结

  1. 首先,Golang gc不是引用计数,采用是mark+sweep的方式,这种方法天然就会把gc压力集中起来,导致性能瓶颈。
  2. 不断的性能改进:
    • Go 1.3之前:主要靠STW(stop the world),停下来之后开始扫描,然后把扫不到的清理掉。蠢是蠢了掉,毕竟这个时候也还没开始自举。
    • Go 1.3:小优化,mark完了就马上放开STW,后面再清理。
    • Go 1.5:三色标记扫描+写屏障三色扫描的设计可以把扫描任务分解,利于并行处理,这当然能加一点速;为了干掉STW,搞出来了一个写屏障(增加引用和删除引用两种情况),应用在堆对象上,栈对象为了保证速度不能用这种写屏障,最后还是有一段STW。两种优化上去之后,速度基本能work了。
    • Go 1.8:三色标记扫描+混合写屏障,此时的优化主要在写屏障上,栈对象还是不应用写屏障,但通过一些处理可以规避后续耗时的STW(gc开始时就扫描所有栈对象引用,全部标黑);堆对象用了更高效的混合写屏障,速度也提升了。这个版本的gc已经能称得上优秀。
  3. 总的思路就是把集中的大规模gc变成并行的、尽量不STW的持续过程,gc的吞吐量减少了,给应用的压力也就小了。
  4. 本质上还是区别于java的gc方式,应用场景聚焦于高并发、高io、而并非计算密集的场景