JVM GC工作很奇怪

时间:2015-06-06 17:48:28

标签: java garbage-collection jvm g1gc

在尝试了大量不同的JVM GC设置并进行大量测试后,我遇到了长时间主要GC暂停的问题,我现在正在使用G1GC JVM GC进行测试。除此之外,我还使用性能监视器收集数据,只有正在运行的应用程序(在系统服务旁边......)才是我的应用程序的GlassFish服务器。我没有在性能监视器日志中发现任何奇怪的事情(CPU使用率约为5-10%,当GC发生时,它会略高一些,内存使用率约为60%,......)。现在是测试的第五天,我注意到了以下内容:

enter image description here

直到第二次主要(混合)GC发生一切都很好(次要GC长约20ms,GC性能为160000M / s,......)。第二个主要的GC需要大约2秒钟(很长时间 - 首先花费150毫秒,但并不重要),之后较小的GC比以前长得多(参见图中的灰线表示次要(年轻)GC的持续时间)和GC性能只有12000M / s并且仍在下降。我想知道为什么在第二个主要GC之后发生这种情况,即使没有其他应用程序正在运行且CPU /内存使用情况与以前相同。我不知道这里发生了什么。我还有一个问题 - 我在不同的PC上运行相同的测试,它具有较少的RAM和较旧的处理器和GC性能大约5000M / s(小型GC大约50-100ms)我认为这是正常的,因为更糟的处理器并减少RAM。奇怪的是,主要的GC在运行3天后还没有发生,老一代的增长速度比这里慢得多,即使设置相同。为什么增长要慢得多(两天内大约150MB,三天内第二台PC 80 MB)?谢谢你的所有答案,我不知道为什么GC表现得如此异常(首先它工作正常然后表现正在恶化)。

编辑:here是完整的GC日志文件,它是在GCViewer中导入的,还有来自GCViewer的事件详细信息统计信息:

enter image description here

记录第3个主要GC:

2015-06-08T08:09:13.123+0200: 572815.533: [GC concurrent-root-region-scan-start]
2015-06-08T08:09:13.139+0200: 572815.560: [GC concurrent-root-region-scan-end, 0.0271771 secs]
2015-06-08T08:09:13.139+0200: 572815.560: [GC concurrent-mark-start]
2015-06-08T08:09:16.302+0200: 572818.721: [GC concurrent-mark-end, 3.1612900 secs]
2015-06-08T08:09:16.318+0200: 572818.729: [GC remark 572818.729: [Finalize Marking, 0.0002590 secs] 572818.729: [GC ref-proc, 0.4479462 secs] 572819.177: [Unloading, 3.2004912 secs], 3.6499382 secs]
 [Times: user=0.20 sys=0.08, real=3.64 secs] 

同样,实时比用户+ sys高得多,卸载阶段耗时超过3秒。

2 个答案:

答案 0 :(得分:1)

如果没有深入研究这个问题,我们无法为您提供经过验证的解释,但请试试。

您最有可能阅读G1 GC oracle文档,并且知道此收集器是针对具有大堆的应用程序而制作的。它旨在减少主要垃圾收集期间的长时间暂停。

在您的示例中,我们可以看到,在主要GC之后,次要GC暂停会立即增加。我不知道G1的内部机制,但是直觉告诉我第二个主要的GC是内部信号" G1用于分析其性能(他是否实现了吞吐量目标/暂停目标)。所以在我看来,经过这次分析,G1决定改变其内部参数。我敢打赌,长时间的小GC暂停表明G1增加了年轻一代的空间。

他为什么这样做?那么,更大的年轻一代将降低对老一代的推广速度。所以老一代的空间将被填补得更慢。 G1很可能试图阻止下一个主要的GC暂停时间长达前一个(2秒)。

同样,我不能保证事情就像我说的那样没有深入分析,但我试着给你指示。

你的"慢了#34;机器,工作3天没有主要的GC暂停 - 如果不知道GC配置和应用程序如何工作,真的很难说。我打赌应用程序负载较低。

答案 1 :(得分:1)

由于您似乎关注暂停时间,因此我在JVM标记中看不到任何暂停时间目标。

您可以通过MaxGCMinorPauseMillis(仅次要)和MaxGCPauseMillis(整体)设置暂停时间目标。

这些只是目标,收藏家可能因各种原因未能满足这些目标。默认情况下,GC仅允许在GCing上刻录1%的CPU时间。因此,如果无法实现其目标,您可以尝试设置GCTimeRatio=19以在5%的时间内授予它(暂停时间交换吞吐量)。

日志中最长的暂停似乎就是这个:

2015-06-05T09:14:51.909+0200: 317539.613: [GC remark 317539.613: [Finalize Marking, 0.0003625 secs] 317539.613: [GC ref-proc, 0.9890475 secs] 317540.602: [Unloading, 0.9739555 secs], 1.9643775 secs]

您可以尝试使用-XX:+ParallelRefProcEnabled

降低参考处理时间