Go GC: 优先考虑效率和简洁

未匹配的标注

本文为官方 Go Blog 的中文翻译,详见 翻译说明

Richard Hudson
2015 年 8 月 31 日

计划#

Go 不仅要在 2015 年而且要在 2025 年及以后建立垃圾收集器 (GC):一个支持今天的软件开发并在未来十年扩展规模以及新软件和硬件的垃圾收集器 (GC)。这样的未来无处使用 stop-the-world GC 暂停,这已经成为更广泛使用 Go 等安全语言的障碍。

Go 1.5 是我们对未来的第一印象,它的 GC 延迟远低于我们一年前设定的 10 毫秒目标。我们在 Gophercon 上的演讲中展示了一些令人印象深刻的数字。延迟的改进引起了很多关注。 Robin Verlangen 的博客文章每天数十亿个请求满足 Go 1.5 通过端到端的结果验证我们的方向。我们还特别喜欢 Alan Shreve 的生产服务器图表和他的 “减少了 85%的神圣” 评论。

如今,16 GB 的 RAM 成本为 100 美元,CPU 带有许多内核,每个内核具有多个硬件线程。在十年之内,这种硬件看似少见的,但如今在 Go 中构建的软件将需要扩展,以满足不断增长的需求和下一个重大挑战。考虑到硬件将提供提高吞吐量的能力,Go 的垃圾收集器的设计宗旨是仅通过旋钮即可实现低延迟和优化。 Go 1.5 是这条道路上的第一步,而这些第一步将永远影响 Go 及其最佳支持的应用程序。这篇博客文章从高层次概述了我们为 Go 1.5 收集器所做的工作。

点缀#

为了在接下来的十年中创建垃圾收集器,我们转向了几十年前的算法。 Go 的新垃圾收集器是 concurrenttri-colormark-sweep 收集器,[Dijkstra 于 1978](dl.acm.org/citation.cfm?id= 359655) 年首次提出。这与当今大多数 “企业” 级垃圾收集器是有意不同的,我们认为它非常适合现代硬件的属性和现代软件的延迟要求。

在三色收集器中,每个对象都是白色,灰色或黑色,我们将堆视为已连接对象的图形。在 GC 周期开始时,所有对象均为白色。 GC 会访问所有 root,它们是应用程序可直接访问的对象,例如全局变量和堆栈中的东西,并为这些灰色着色。然后,GC 选择一个灰色对象,使其变黑,然后对其进行扫描以寻找指向其他对象的指针。当此扫描找到指向白色对象的指针时,它将变成灰色。重复此过程,直到没有其他灰色物体为止。在这一点上,已知白色物体是无法到达的并且可以重复使用。

所有这一切都与应用程序 (mutator) 同时发生,在收集器运行时更改指针。因此,更改器必须保持不变,即没有黑色对象指向白色对象,以免垃圾收集器无法跟踪安装在它已经访问过的一部分堆中的对象。保持此不变性是 write barrier 的工作,它是每当修改堆中的指针时 mutator 运行的一个小函数。 Go 的写入屏障将当前可访问的对象变为灰色,如果它当前为白色,以确保垃圾收集器最终对其进行扫描以查找指针。

如果我们希望避免阻塞变色子,那么确定何时找到所有灰色物体的工作就很难确定,并且可能既昂贵又复杂。为使事情简单起见,Go 1.5 会同时完成尽可能多的工作,然后短暂停止工作以检查所有可能的灰色物体来源。Go 1.6 的主要交付内容是,找到最终 stop-the-world 所需的时间与该 GC 所做的工作总量之间的最佳结合点。

当然,魔鬼在细节中。我们什么时候开始 GC 周期?我们使用什么指标来做出决定? GC 应该如何与 Go 调度程序进行交互?我们如何暂停更改程序线程足够长的时间以扫描其堆栈?我们如何表示白色,灰色和黑色,以便我们可以有效地查找和扫描灰色物体?我们怎么知道根在哪里?我们如何知道指针在对象中的位置?我们如何最小化内存碎片?我们如何处理缓存性能问题?堆应该多大?并不断地,一些与分配有关,一些与找到可到达的对象有关,一些与调度有关,但是许多与性能有关。这些领域中每个领域的低级讨论都超出了本博文的范围。

在更高级别上,解决性能问题的一种方法是添加 GC 旋钮,每个性能有一个旋钮。然后,程序员可以旋转旋钮以搜索适合其应用的设置。不利的一面是,十年后每年使用一个或两个新旋钮,您最终会遇到《 GC 旋钮开关使用法》。 Go 不会走那条路。相反,我们提供了一个称为 GOGC 的旋钮。此值控制相对于可访问对象的大小的堆的总大小。默认值 100 表示总堆大小现在比上一次收集之后可访问对象的大小大 100%(即,两倍)。 200 表示总堆大小比可访问对象的大小大 200%(即三倍)。如果要减少花费在 GC 上的总时间,请增加 GOGC。如果您想用更多的 GC 时间来换取更少的内存,请降低 GOGC。

更重要的是,随着下一代硬件将 RAM 加倍,仅将 GOGC 加倍将使 GC 周期数减半。另一方面,由于 GOGC 基于可到达对象的大小,因此通过将可到达对象增加一倍来增加负载不需要重新调整。该应用程序可以扩展。此外,不受持续支持数十个旋钮的困扰,运行时团队可以根据来自实际客户应用程序的反馈专注于改善运行时。

妙处#

Go 1.5 的 GC 迎来了一个未来,即世界停顿不再是使用安全语言的障碍。在未来,应用程序可以与硬件一起轻松扩展,并且随着硬件功能的增强,GC 不会成为更好,更具扩展性的软件的障碍。未来十年乃至以后都是一个好地方。有关 1.5 GC 以及我们如何消除延迟问题的更多详细信息,请参见 Go GC:解决延迟问题的演示文稿或 [幻灯片](https:///talks.golang.org/2015/go-gc.pdf)。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/go-blog/go15gc/...

译文地址:https://learnku.com/docs/go-blog/go15gc/...

上一篇 下一篇
Summer
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~