【发布时间】:2018-07-23 09:36:02
【问题描述】:
我最近将我的 Java 应用程序从 CMS + ParNew 切换到了 G1GC。 我在切换时观察到的是 CPU 使用率升高了,GC 计数 + 暂停时间也升高了。 切换前我的 JVM 标志是
java -Xmx22467m -Xms22467m -XX:NewSize=11233m -XX:+UseConcMarkSweepGC -XX:AutoBoxCacheMax=1048576 -jar my-application.jar
切换后我的标志是:
java -Xmx22467m -Xms22467m -XX:+G1GC -XX:AutoBoxCacheMax=1048576 -XX:MaxGCPauseMillis=30 -jar my-application.jar
我遵循了 Oracle 的最佳实践http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
Do not Set Young Generation Size
并且没有设置年轻代的大小。 但是我怀疑年轻一代的大小是这里的问题。 我看到的是堆使用量在 ~6 - 8 GB 之间波动。
而在此之前,使用 CMS 和 Par New,内存使用量在 4-16 GB 之间增长,然后我才看到 GC:
我不确定我是否理解为什么 G1GC GC 如此频繁。我不确定在使用 G1GC 进行 GC 调整时我缺少什么。
我正在使用 Java 8: ava 版本“1.8.0_144” Java(TM) SE 运行时环境 (build 1.8.0_144-b01) Java HotSpot(TM) 64 位服务器 VM(内部版本 25.144-b01,混合模式)
感谢您的帮助。
更新: 有关这些暂停的更多信息: 正如您所看到的,所有这些暂停都是 G1New,并且似乎它们与我的目标暂停时间一样长,即 30 毫秒。 当我在切换到 G1GC 之前查看 ParNew 暂停时,它看起来是这样的: 所以它们也都是年轻代集合(ParNew),但它们的频率较低且较短,因为它们仅在堆使用量达到 14GB 左右时才会发生(根据图表)
我仍然不知道为什么 G1New 会这么早发生(就堆使用而言)
更新 2 我还注意到 NewRatio=2,我不知道 G1GC 是否尊重这一点,但这意味着我的 New Gen 的上限为 7GB。会不会是这个原因?
更新 3 添加 G1GC GC 日志: https://drive.google.com/file/d/1iWqZCbB-nU6k_0-AQdvb6vaBSYbkQcqn/view?usp=sharing
【问题讨论】:
-
好的。将年轻代大小设置为 16 GB,看看是否有区别。您比我们更了解您的应用程序。
-
看起来这个应用程序制造了很多容易处理的短命垃圾。 G1应该很合适。应该能够将 XX:InitiatingHeapOccupancyPercent 设置为相当高的 75 或 80,这应该使 GC 图看起来更像 CMS 图。
-
@JonahB 您在图像中看到的所有 GC 周期都是 G1New。如果我误解了 XX:InitiatingHeapOccupancyPercent 的含义,请纠正我。并发标记周期不是老一代集合的一部分吗? (在 G1 Collection Phases - Concurrent Marking Cycle Phases 部分查看oracle.com/technetwork/tutorials/tutorials-1876574.html)。如果是这样,提高该值将如何阻止 G1New 周期?
-
@ElliottFrisch,感谢您的回复。根据Oracle,如果我设置年轻代大小,G1GC 将不尊重目标暂停时间。 “通过 -Xmn 显式设置年轻代大小会干扰 G1 收集器的默认行为。G1 将不再尊重收集的暂停时间目标。因此,本质上,设置年轻代大小会禁用暂停时间目标。G1 不再是能够根据需要扩展和收缩年轻代空间。由于大小是固定的,所以不能改变大小"
-
您可能还想尝试将 -Xms 设置为 低于 的值,而不是 -Xmx,从而为 VM 中的调整启发式算法提供一些发挥空间。
标签: java java-8 garbage-collection jvm g1gc