Java 无法使用 TB 的 RAM,因为 GC 暂停时间太长(几分钟)。随着最近对 Go GC 的更新,我想知道它的 GC 暂停是否足够短,可以用于大量 RAM,例如几 TB。
目前有这方面的基准吗?我们现在可以使用具有这么多 RAM 的垃圾收集语言吗?
最佳答案
tl;dr:
- 目前,您无法在单个 Go 进程中使用 TB 的 RAM。 Linux 上的最大容量为 512 GB,而我所见测试的最大容量为 240 GB。
- 在当前的后台 GC 下,GC 工作量往往比 GC暂停更重要。
- 您可以将 GC 工作负载理解为 指针 * 分配率/备用 RAM。在使用大量 RAM 的应用程序中,只有那些指针少或分配少的应用程序的 GC 工作量才会低。
我同意 inf 的评论,即大堆值得向其他人询问(或测试)。 JimB 指出,Go 堆目前的硬限制为 512 GB,而 18 240 GB 是我所见过的最大测试。
我们对大堆的一些了解,来自 the design document和 the GopherCon 2015 slides :
- 1.5 收集器的目的不是减少 GCwork,只是通过在后台工作来减少 pauses。
- 您的代码在 GC 扫描堆栈和全局指针时暂停。
1.5 GC 在大约 18GB 堆的 GC 基准测试中有短暂的停顿,如 this graph from the GopherCon talk 底部最右边的黄点所示:
运行几个最初有大约 300 毫秒暂停的生产应用程序的人报告下降到 ~4ms和 ~20ms .另一个应用程序报告他们的第 95 个百分位 GC 时间从 279ms to ~10ms 开始。 .
转到 1.6 added polish and pushed some of the remaining work to the background .结果,堆超过 200GB 的测试仍然看到最大暂停时间为 20 毫秒,如 a slide 所示。 2016 年初 State of Go talk :
在 1.5 以下有 20 毫秒暂停时间的同一应用程序有 3-4ms pauses under 1.6, with about an 8GB heap and 150M allocations/minute .
使用 Go 作为聊天服务的 Twitch 报告说 by Go 1.7 pause times had been reduced to 1ms with lots of running goroutines .
1.8 took stack scanning out of the stop-the-world phase ,即使在大堆上,大多数停顿时间也低于 1 毫秒。 Early numbers look good .有时应用程序仍然具有使 goroutine 难以暂停的代码模式,从而有效地延长了所有其他线程的暂停时间,但通常可以公平地说 GC 的后台工作现在通常比 GC 重要得多 暂停。
关于垃圾收集的一些一般性观察,不特定于 Go:
- 收集的频率取决于您愿意为进程提供的 RAM 用完的速度。
- 每个集合所做的工作量部分取决于正在使用的指针数量。 (包括 the pointers within slices, interface values, strings, etc.)
换个说法,如果应用程序只有几个指针(例如,它处理相对较少的大 []byte
缓冲区)并且收集发生较少的情况下,访问大量内存的应用程序可能仍然没有 GC 问题通常在分配率低的情况下(例如,因为您应用 sync.Pool
以在您最快速地咀嚼 RAM 的任何地方重用内存)。
因此,如果您正在查看涉及数百 GB 堆的东西,而这些堆对 GC 不友好,我建议您考虑任何一个
- 用 C 或类似语言编写
- 将大量数据移出对象图。例如,您可以管理嵌入式数据库中的数据,如
bolt
。 ,将其放在外部数据库服务中,或使用groupcache
之类的东西或者 memcache,如果你想要更多的缓存而不是数据库 - 运行一组较小的堆而不是一个大的进程
- 只需仔细进行原型(prototype)设计、测试和优化以避免内存问题。
关于go - 带有 TB RAM 的 go 1.5 gc 有多快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31684862/