提问者:小点点

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


我最近将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

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

我感谢你的帮助。

我仍然不知道为什么 G1New 发生得这么早(就堆使用而言)

更新2我还注意到NewRatio=2,我不知道G1GC是否尊重这一点,但这将意味着我的新一代上限为7GB。可能是这个原因吗?

更新3添加G1GC GC日志:https://drive.google.com/file/d/1iWqZCbB-nU6k_0-AQdvb6vaBSYbkQcqn/view?usp=sharing


共2个答案

匿名用户

我能够看到复制对象所花费的时间非常重要。看起来 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:G1RSetRegionEntrys。

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

我仍然看到的是,在年轻撤离中[已处理缓冲区]仍然需要很长时间,在混合收集中[扫描rs]非常长。不知道为什么

匿名用户

您的GC日志显示平均GC暂停间隔为2秒,每次大约30-40毫秒,相当于应用程序吞吐量的95%左右。这并不等同于“杀人表演”的领域。至少不是因为GC暂停。

不过,G1会做更多的并发工作,例如,对于记住的集合细化,您的暂停似乎会在更新/扫描RS上花费一些时间,所以我假设并发GC线程也很忙,即在GC暂停之外可能需要额外的CPU周期,默认情况下日志不涵盖这一点,您需要G1SummarizeRSetStats。如果延迟更重要,您可能希望为机器分配更多内核,如果吞吐量更重要,您可以调整G1以在暂停期间执行更多RS更新(以增加暂停时间为代价)。