Java jvmgc工作非常奇怪

Java jvmgc工作非常奇怪,java,garbage-collection,jvm,g1gc,Java,Garbage Collection,Jvm,G1gc,在尝试了许多不同的jvmgc设置并进行了大量测试之后,我遇到了长时间的主要GC暂停问题,现在我正在使用g1gcjvmgc进行测试。除此之外,我还使用性能监视器收集数据,只有运行的应用程序(除了系统服务,…)是我的应用程序的GlassFish服务器。我在性能监视器日志中没有发现任何奇怪的地方(CPU使用率约为5-10%,当GC发生时,CPU使用率会升高一点,内存使用率约为60%…)。现在是测试的第五天,我注意到以下几点: 在第二次主要(混合)GC出现之前,一切正常(次要GC约20毫秒长,GC性能

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

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

编辑:是在GCViewer中导入的完整GC日志文件,也是GCViewer中的事件详细信息统计:

第三个主要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] 

同样,实时性远高于用户+系统,卸载阶段耗时超过3秒。

如果不深入研究问题,就无法给您一个经过验证的解释,但让我们试试

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

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

他为什么这么做?嗯,年轻一代越大,对老一代的提升速度就越慢。所以老一代的空间将被慢慢填满。最有可能的是G1试图阻止下一次主要GC暂停与前一次一样长(2秒)

再一次,我不能保证事情在没有深入分析的情况下会像我所说的那样进行,但我试着给你们指明方向


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

因为您似乎关心暂停时间,所以我在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

降低参考处理时间。请描述颜色的含义以及这些增长线代表的内容。我们能在这里看到主要GC的持续时间吗?如果是,它们在哪里?您能否提供感兴趣的时间跨度的原始GC日志?还要确保使用
-XX:+PrintGCDetails
确定,紫色线是永久(旧)代,蓝色线用于堆(因此基本上是年轻一代,因为它从老一代开始),下面的灰色线是次要GC时间,主要GC时间(旧一代的并发收集;不是完全GC)是堆大小下降的两条黄线(第一条花了0,1秒,第二条几乎2秒)。此图来自GCViewer应用程序。我将立即上载原始GC日志。我编辑了我的帖子,从GCViewer添加了GC日志和事件详细信息。我建议日志文件使用GIST或pastebin,而不是文件托管服务。谢谢您的回答。你们所写的解释了为什么小型GC更长——所以旧一代的空间填充会更慢,我认为这也可以从图中看出(紫色线的增长速度比以前慢)。我没有想到这一点。是的,我阅读了所有GC的文档,我也尝试了所有GC,但除了G1GC()之外,所有GC都暂停了很长时间。我还使用了性能监视器,但没有发现任何有用的东西。也许G1GC也试图阻止像这里这样的较慢机器上的主要GC…但如果GC真的决定这样做,这意味着吞吐量和GC性能将降低(现在GC性能降低约20%,吞吐量目前仅为0,02%)。我真的很想知道下一个主要GC会持续多久。如果由于堆的大小太小,您建议我不要在服务器上使用G1GC,您能告诉我吗?如果是这样的话,你能告诉我CMS使用什么设置来减少暂停时间吗(请参阅我在之前评论中发布的链接的其他问题?谢谢…,正如@the8472所提到的,你可以