Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

Google Go 团队的成员 Richard L. Hudson (Rick) 近日在 Go 的官方博客和大家分享了他在2018年6月18日国际内存管理研讨会(ISMM)上发表的主题演讲稿。在过去的25年里,ISMM 一直是发布内存管理和垃圾回收论文的首选场所,而 Rick 也因其在内存管理方面的工作而被大家熟知。

Rick 是内存管理方面的专家,发明了 Train, Sapphire 和 Mississippi Delta 等算法,其中 GC stack maps 算法使得静态类型语言(比如:Modula-3, Java, C# 和 Go)的垃圾回收成为可能。他还发表了很多关于语言运行时内存管理、并发、并行、内存模型、事务内存的文章。Rick 作为 Google Go 团队的一员,负责 Go 的 GC 和运行时的问题。

Risk 在演讲稿中先是介绍了 Go GC 取得的成功。

Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

Go 的应用程序中有数十万个堆栈(stacks),它们由 Go scheduler 调度程序管理,并总是在 GC safepoints 处被抢占。Go scheduler 调度程序将 Go routines 多路复用到 OS 线程上,希望每个 HW 线程使用一个 OS 线程来运行。通过复制它们并更新堆栈中的指针来管理堆栈及其大小,这是一个本地操作,因此它可以很好地扩展。

Go 语言包含两大可调节的方法来控制 GC,一个是 SetGCPercent,另一个则是 SetMaxHeap。前者可以调整你想要使用多少 CPU 以及你想要使用多少内存。后者尚未发布但正在内部使用和评估,它允许程序员设置最大的堆内存大小应该是多少,MaxHeap 还提供了更多的调度灵活性,运行时(runtime)可以将堆的大小调整为 MaxHeap。

Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

而对于 Go 语言的 GC 延迟问题,开发团队为解决它们付出了巨大的心血。从2014年开始,最初的计划是做一个无 read barrier 的并发复制GC,因为读取的开销存在很大的不确定性,所以 Go 想要避免它们。

Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

但当时由于编译器的性能限制所在,后来他们放弃了实现“复制”部分。

Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

然后 Risk 谈到了最终推动 GC 延迟问题走向成功的 GC Pacer,它确定何时最佳地启动 GC 循环,当然它做的远不止这些,这只是基本方法。

谈到成功,自然也会有失败。Risk 和大家分享了类似 ROC(Request Oriented Collecter) 这种方案的失败尝试,他们采用 ROC 方案后,发现这反而降低了 write barrier 的速度。

Go 语言的垃圾回收演化历程:垃圾回收和运行时问题

谈到 Go 语言的未来方向方面,Risk 表示不打算增加 GC API surface,现在已经很合适,并且没有一个应用程序重要到足以让他们添加新标志。他们还将研究如何改进已经非常好的逃逸分析并优化 Go 的“面向价值(value-oriented)”编程。不仅在编程中,还包括为用户提供的工具中。在算法上,将关注设计空间的一些部分。

最后,Risk 表示希望摩尔定律在接下来的5年中能更好的体现在 RAM 而不是 CPU。

更多内容请查看原文 https://blog.golang.org/ismmkeynote