我最近将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.htmlDo 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运行时环境(内部版本1.8.0_144-b01)
Java HotSpot(TM)64位服务器VM(内部版本25.144-b01,混合模式)
我感谢您的帮助。
UPDATE :
有关这些暂停的更多信息:
如您所见,所有这些暂停都是G1New,而且看起来与我的目标暂停时间一样长,即30ms。
当我查看切换到G1GC之前的ParNew暂停时,它是这样的:
因此它们也都是年轻的gen集合(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
最佳答案
您的GC日志显示平均GC暂停间隔为2秒,每个间隔为30-40ms,这相当于应用程序吞吐量的95%左右。那并不等于“杀人绩效”。至少不是由于GC暂停造成的。
G1可以做更多的并发工作,例如为了记住集细化条件,您的停顿似乎在update/scan RS中花费了一些时间,因此我假设并发GC线程也很忙,即,在GC停顿之外它可能需要其他CPU周期,默认情况下日志未涵盖这点,您需要+G1SummarizeRSetStats
为了那个原因。如果延迟更重要,则可能需要为计算机分配更多的内核,如果吞吐量更重要,则可以调整G1以在暂停期间执行更多的RS更新(以增加暂停时间为代价)。