我正在观察频繁的GC,包括在我的java应用程序中加载100个客户机下的完整GC,进行web服务调用,将一个21 to (压缩大小)的JSON返回给客户端。未压缩的JSON大约为200 KB。由于GC频繁,我观察到了2.6秒的巨大延迟。在这里,用于负载测试的JVM选项
-Xloggc:/mnt/apache-tomcat-7.0.29/logs/gc.log -XX:+UseConcMarkSweepGC -XX:+UseCompressedOops -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintTenuringDistribution -XX:+UseParNewGC -Xms5048M -XX:MaxTenuringThreshold=2 -XX:SoftRefLRUPolicyMSPerMB=73 -Djava.net.preferIPv4Stack=true -server -XX:NewRatio=4 -XX:SurvivorRatio=8 我使用的是带有4vCPU和15 MB内存的AWS xLarge实例。
下面是进程生成的GCl日志
249.988: [GC 249.988: [ParNew
2163 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2164 - age 1: 83821968 bytes, 83821968 total
2165 - age 2: 20181408 bytes, 104003376 total
2166 : 896337K->103360K(930432K), 0.0409860 secs] 4453729K->3663260K(5065792K), 0.0412220 secs] [Times: user=0.16 sys=0.00, real=0.04 secs]
2167 250.051: [GC 250.051: [ParNew
2168 Desired survivor size 52920320 bytes, new threshold 2 (max 2)
2169 - age 1: 24997144 bytes, 24997144 total
2170 : 185613K->82956K(930432K), 0.0620620 secs] 3745513K->3744426K(5065792K), 0.0622810 secs] [Times: user=0.22 sys=0.00, real=0.06 secs]
2171 250.408: [GC 250.409: [ParNew
2172 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2173 - age 1: 86010184 bytes, 86010184 total
2174 - age 2: 19119656 bytes, 105129840 total
2183 : 930432K->103360K(930432K), 0.0904080 secs] 4767408K->4080180K(5065792K), 0.0906520 secs] [Times: user=0.33 sys=0.01, real=0.09 secs]
2184 251.229: [GC 251.229: [ParNew: 215470K->215470K(930432K), 0.0000370 secs] 4192291K->4192291K(5065792K), 0.0001620 secs] [Times: user=0.00 sys=0.00, real =0.00 secs]
2185 GC locker: Trying a full collection because scavenge failed
2186 251.229: [Full GC 251.229: [CMS251.495: [CMS-concurrent-mark: 6.443/8.877 secs] [Times: user=30.14 sys=3.55, real=8.87 secs]
2187 (concurrent mode failure): 3976820K->354739K(4135360K), 0.9792960 secs] 4192291K->354739K(5065792K), [CMS Perm : 42722K->42722K(71212K)], 0.9794580 sec s] [Times: user=0.96 sys=0.02, real=0.98 secs]
2188 252.439: [GC 252.440: [ParNew
2189 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2190 - age 1: 105807496 bytes, 105807496 total
2191 : 837144K->103360K(930432K), 0.0562310 secs] 1191884K->474282K(5065792K), 0.0564520 secs] [Times: user=0.22 sys=0.00, real=0.05 secs]
2192 252.676: [GC 252.676: [ParNew
2193 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2194 - age 1: 95836672 bytes, 95836672 total
2195 : 924377K->103360K(930432K), 0.0772210 secs] 1295299K->575312K(5065792K), 0.0774650 secs] [Times: user=0.28 sys=0.01, real=0.08 secs]
2196 253.001: [GC 253.001: [ParNew
2197 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2198 - age 1: 99903544 bytes, 99903544 total
2199 : 930432K->103360K(930432K), 0.0712130 secs] 1405673K->680963K(5065792K), 0.0714420 secs] [Times: user=0.25 sys=0.01, real=0.07 secs]
2200 253.324: [GC 253.324: [ParNew
2201 Desired survivor size 52920320 bytes, new threshold 1 (max 2)
2202 - age 1: 105814880 bytes, 105814880 total
2203 : 930432K->103360K(930432K), 0.0736730 secs] 1513770K->807662K(5065792K), 0.0739490 secs] [Times: user=0.27 sys=0.00, real=0.08 secs]
2204 253.666: [GC 253.667: [ParNew发布于 2013-08-15 11:30:45
我想知道为什么司机们只是简单地回答这个问题,而不至少停下来评论他们为什么要这样做……这让我很烦。
侧重于这一信息:
GC locker: Trying a full collection because scavenge failed我发现这条线:
有了这些资料:
还可以在增量模式( in )下运行CMS,并使用-XX:+CMSIncrementalMode启用。
您是否以(I)模式运行CMS?这似乎对我有帮助,虽然我承认这不是我的专长。只是过来帮忙。
在此将进一步讨论这一问题和可能的解决办法:
https://forums.oracle.com/thread/1543499
另外,重点关注消息“并发模式失败”,这是一个主要问题:How to reduce java concurrent mode failure and excessive gc
发布于 2016-02-15 14:57:02
让我们总结一下您的内存设置:
我想上面提到的15 MB是一个错误。假设您的机器的内存小于19.7GB,选项"-Xms5048M“有效地将最小和最大堆大小设置为5048 MB (默认最大值为机器RAM的25%,因此,如果大于19.7GBRAM,则最大值将更高)。
与选项-XX:NewRatio=4和-XX:SurvivorRatio=8一起,您得到的是以下内存布局:
现在让我们看看JVM从中得到了什么:
从日志中,您可以看到幸存者空间非常小;例如,在第2174行中,年龄1和2项的总和为182 MB,因此远远超过了S0/S1大小。较低的最大寿命(1或2代)也是幸存者空间受限的标志-- JVM将减少最大生存期,因为它试图将幸存者空间利用率削减到目标值(默认情况下为50%)。
第2183行的报告行表明,136.5 MB已从年轻空间提升到终身空间( GC后的年轻gen为930432 KB - 103360 KB = 827072 KB,总的堆diff为4767408 KB - 4080180 KB = 687228 KB,从而提升了139844 KB )。
在第2183行中,您可以看到旧的根使用量为4080180 KB - 103360 KB = 3976820 KB = 3883.6 MB。这只剩下154.8 MB的最大旧的世代大小。
我不喜欢GC算法触发器的细节(据我了解,它们在JVM版本之间确实会发生变化),但考虑到
.很明显迫切需要一个完整的GC
作为一种解决方案,我会尝试增加年轻一代的尺寸
当然,增加堆的总大小也会有帮助,进一步调优SurvivorRatio值也会有帮助;特别是后者是高度依赖于应用程序的,但是,如果不深入了解应用程序和GC算法,我就不会触及它。
https://stackoverflow.com/questions/18251518
复制相似问题