在非交互式应用程序中处理 150GB 堆

Ale*_*rov 5 java performance garbage-collection jvm java-9

您好,我有一个使用内存数据网格的 150GB 堆内存程序。运营部门对我提出了使用单台机器的疯狂要求。现在我们都知道如果并行垃圾收集器使用超过 150GB 时会发生什么,如果调用 FULL GC,可能会需要数十分钟的垃圾收集。

我希望 Java 9 能够推出 Shenandoah 低暂停 GC。不幸的是,据我所知,它没有在 Java 9 中列出。有人对此了解吗?

尽管如此,我想知道 G1 GC 对于这么大的堆内存将如何执行。

最后一个问题。因为我有非交互式批处理应用程序,应该在 2 小时内完成,所以可以说。这里的主要目标是确保 Full GC 永远不会启动。如果我确保有足够的内存,假设可以达到的最大堆为 150,并且我分配了 250GB,我可以很有信心地说 Full GC GC 永远不会启动还是?通常如果新生代+老生代达到最大堆就会触发full GC。可以用不同的方式触发吗?

有一个重复的请求,我将尝试在这里解释为什么这个问题不是重复的。首先我们讨论的是 150GB 堆,它为问题添加了完全不同的维度。其次,我不使用 RMI,因为它是在提到的问题中,第三,我在字里行间询问有关 G1 垃圾收集器的问题。此外,一旦我们超出 32GB 堆屏障,我们就会进入 64 位地址空间,你无法让我相信关于<32GB堆的问题与关于堆>32GB的问题是相同的,更不用说自从Java 7(例如PermSpace)不存在以来,事情已经发生了一些变化。

the*_*472 5

压缩 GC 的经验法则是每个核心每秒应该能够处理 1 GB 的活动对象。

Haswell i7(4 核/8 线程)和 20GB 堆以及并行收集器的示例:

[24.757s][info][gc,heap        ] GC(109) PSYoungGen: 129280K->0K(917504K)
[24.757s][info][gc,heap        ] GC(109) ParOldGen: 19471666K->7812244K(19922944K)
[24.757s][info][gc             ] GC(109) Pause Full (Ergonomics) 19141M->7629M(20352M) (23.791s, 24.757s) 966.174ms
[24.757s][info][gc,cpu         ] GC(109) User=6.41s Sys=0.02s Real=0.97s
Run Code Online (Sandbox Code Playgroud)

压缩后的live set大小为7.6GB。由于并行性,这需要 6.4 秒的 CPU 时间,这意味着 <1 秒的暂停时间。

原则上,并行收集器应该能够在多核系统上以<约2分钟的完整GC时间处理150GB堆,即使堆的大部分由活动对象组成。

当然,这只是一个经验法则。一些可能对其产生负面影响的事情:

  • 寻呼
  • CPU 热调节
  • 由非常大的、引用较多的对象组成的工作负载
  • NUMA 配置中的非本地内存流量
  • 其他进程竞争CPU时间
  • 大量使用弱/软引用

在某些情况下,可能需要进行调整才能实现此吞吐量。

如果尽管如此,并行收集器仍无法工作,那么 CMS 和 G1 可以成为可行的替代方案,但前提是有足够的备用堆容量和 CPU 核心可供 JVM 使用。他们需要足够的喘息空间来完成并发工作,而不会有发生完整 GC 的风险。

我说没有互动是正确的,但我仍然有严格的许可协议。我需要在一小时内完成整个处理。所以我无法承受30分钟停止世界大事。

基本上,您并不真正需要 CMS、G1、Shenandoah 或 Zing 所追求的低暂停时间(它们的目标是 <100ms,甚至在大堆上甚至 <10ms)。

您所需要的只是 STW 暂停不会严重到占用您大部分计算时间的程度。

对于大多数可用的收集器来说,这应该是可行的,忽略串行收集器。

在实践中,存在一些病态的边缘情况,它们可能会崩溃,但要达到这一点,您需要根据实际工作负载设置一个系统并进行一些测试运行。如果您遇到一些实际问题,那么您可以提出更详细的问题。