java - G1GC 非常高的 GC 计数和 CPU,非常频繁的 GC 会降低性能

标签 java java-8 garbage-collection jvm g1gc

我最近将我的 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 之间波动。 Heap usage

而之前,使用 CMS 和 Par New 时,内存使用量增加了 4-16 GB,直到那时我才看到 GC: enter image description here

我不确定我是否理解为什么 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,混合模式)

感谢您的帮助。

更新: 有关这些暂停的更多信息: enter image description here 如您所见,所有这些暂停都是 G1New,而且看起来它们与我的目标暂停时间一样长,即 30 毫秒。 当我查看切换到 G1GC 之前的 ParNew 暂停时,它是这样的: enter image description here 所以它们也都是新生代收集(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

最佳答案

我能够看到复制对象所花费的时间非常可观。看起来 G1GC 在对象被提升为永久代之前默认有 15 代。 我将它减少到 1 (-XX:MaxTenuringThreshold=1)

我也不知道如何在日志中确认它,但是可视化 GC 日志我看到年轻代的大小不断调整,从最小大小到最大大小。我缩小了范围,这也提高了性能。

看这里https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector-tuning.htm#JSGCT-GUID-70E3F150-B68E-4787-BBF1-F91315AC9AB9 我试图弄清楚粗化是否确实是一个问题。但它只是说要设置 gc+remset=trace ,我不明白如何在命令行中传递给 java,如果它在 JDK 8 中可用。 为了以防万一,我增加了 XX:G1RSetRegionEntries。

我希望它对 future 的 G1GC 调谐器有所帮助,如果其他人有更多建议,那就太好了。

我仍然看到的是 [Processed Buffers] 在年轻疏散中仍然需要很长时间,而 [Scan RS] 在混合集合中很长。 不知道为什么

关于java - G1GC 非常高的 GC 计数和 CPU,非常频繁的 GC 会降低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48759638/

相关文章:

java - Spring 了解 YAML 中的属性

java - 从 Java 代码调用 shell 命令时无法获取输出

java - 从 Eclipse 集合 IntList/IntIterable 创建 IntStream 和 Stream<Integer>

java - 我有一个以文件名作为输入的方法,应该返回一个数组作为输出。该文件包含带有科目名称和分数的学生记录

visual-studio - 是否可以实现 GC.GetAliveInstancesOf<T>() (用于调试)?

去 GC 停止我的 goroutine?

java - 字符串文字的垃圾收集

java - JList渲染不可见 "selection marker"

java - ConcurrentKafkaListenerContainerFactory 的 Spring-Kafka 消费者组协调

java - Spark 提交中不支持的类版本错误