GC调整 - 阻止完整GC

时间:2012-03-20 18:14:09

标签: java garbage-collection jvm performance

我正在尝试避免使用Full GC(来自下面的gc.log示例) 在生产中运行Tomcat中的Grails应用程序。 关于如何更好地配置GC的任何建议?

14359.317:[Full GC 14359.317:[CMS:3453285K-> 3099828K(4194304K),13.1778420 secs] 4506618K-> 3099828K(6081792K),[CMS Perm:261951K-> 181304K(264372K)] icms_dc = 0,13.1786310秒] [时间:用户= 13.15 sys = 0.04,真实= 13.18秒]

我的VM参数如下:
-Xms = 6G
-Xmx = 6G
-XX:MaxPermSize = 1G
-XX:NewSize = 2G
-XX:MaxTenuringThreshold = 8
-XX:SurvivorRatio = 7
-XX:+ UseConcMarkSweepGC
-XX:+ CMSClassUnloadingEnabled
-XX:+ CMSPermGenSweepingEnabled
-XX:+ CMSIncrementalMode
-XX:CMSInitiatingOccupancyFraction = 60
-XX:+ UseCMSInitiatingOccupancyOnly
-XX:+ HeapDumpOnOutOfMemoryError
-XX:+ PrintGCDetails
-XX:+ PrintGCTimeStamps
-XX:+ PrintTenuringDistribution
-Dsun.reflect.inflationThreshold = 0

    14169.764: [GC 14169.764: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   15584312 bytes,   15584312 total
    - age   2:   20053704 bytes,   35638016 total
    - age   3:   13624872 bytes,   49262888 total
    - age   4:   14469608 bytes,   63732496 total
    - age   5:   10553288 bytes,   74285784 total
    - age   6:   11797648 bytes,   86083432 total
    - age   7:   12591328 bytes,   98674760 total
    : 1826161K->130133K(1887488K), 0.1726640 secs] 5216326K->3537160K(6081792K) icms_dc=0 , 0.1733010 secs] [Times: user=0.66 sys=0.03, real=0.17 secs] 
    14218.712: [GC 14218.712: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   25898512 bytes,   25898512 total
    - age   2:   10308160 bytes,   36206672 total
    - age   3:   16927792 bytes,   53134464 total
    - age   4:   13493608 bytes,   66628072 total
    - age   5:   14301832 bytes,   80929904 total
    - age   6:   10448408 bytes,   91378312 total
    - age   7:   11724056 bytes,  103102368 total
    - age   8:   12299528 bytes,  115401896 total
    : 1807957K->147911K(1887488K), 0.1664510 secs] 5214984K->3554938K(6081792K) icms_dc=0 , 0.1671290 secs] [Times: user=0.61 sys=0.00, real=0.17 secs] 
    14251.429: [GC 14251.430: [ParNew
    Desired survivor size 107347968 bytes, new threshold 7 (max 8)
    - age   1:   25749296 bytes,   25749296 total
    - age   2:   20111888 bytes,   45861184 total
    - age   3:    7580776 bytes,   53441960 total
    - age   4:   16819072 bytes,   70261032 total
    - age   5:   13209968 bytes,   83471000 total
    - age   6:   14088856 bytes,   97559856 total
    - age   7:   10371160 bytes,  107931016 total
    - age   8:   11426712 bytes,  119357728 total
    : 1825735K->155304K(1887488K), 0.1888880 secs] 5232762K->3574222K(6081792K) icms_dc=0 , 0.1895340 secs] [Times: user=0.74 sys=0.06, real=0.19 secs] 
    14291.342: [GC 14291.343: [ParNew
    Desired survivor size 107347968 bytes, new threshold 7 (max 8)
    - age   1:   25786480 bytes,   25786480 total
    - age   2:   21991848 bytes,   47778328 total
    - age   3:   16650000 bytes,   64428328 total
    - age   4:    7387368 bytes,   71815696 total
    - age   5:   16777584 bytes,   88593280 total
    - age   6:   13098856 bytes,  101692136 total
    - age   7:   14029704 bytes,  115721840 total
    : 1833128K->151603K(1887488K), 0.1941170 secs] 5252046K->3591384K(6081792K) icms_dc=0 , 0.1947390 secs] [Times: user=0.82 sys=0.04, real=0.20 secs] 
    14334.142: [GC 14334.143: [ParNew
    Desired survivor size 107347968 bytes, new threshold 6 (max 8)
    - age   1:   31541800 bytes,   31541800 total
    - age   2:   20826888 bytes,   52368688 total
    - age   3:   19155264 bytes,   71523952 total
    - age   4:   16422240 bytes,   87946192 total
    - age   5:    7235616 bytes,   95181808 total
    - age   6:   16549000 bytes,  111730808 total
    - age   7:   13026064 bytes,  124756872 total
    : 1829427K->167467K(1887488K), 0.1890190 secs] 5269208K->3620753K(6081792K) icms_dc=0 , 0.1896630 secs] [Times: user=0.80 sys=0.03, real=0.19 secs] 
    14359.317: [Full GC 14359.317: [CMS: 3453285K->3099828K(4194304K), 13.1778420 secs] 4506618K->3099828K(6081792K), [CMS Perm : 261951K->181304K(264372K)] icms_dc=0 , 13.1786310 secs] [Times: user=13.15 sys=0.04, real=13.18 secs]
    14373.287: [GC [1 CMS-initial-mark: 3099828K(4194304K)] 3100094K(6081792K), 0.0107380 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
    14373.298: [CMS-concurrent-mark-start]
    14472.579: [GC 14472.579: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   42849392 bytes,   42849392 total
    : 1677824K->86719K(1887488K), 0.1056680 secs] 4777652K->3186547K(6081792K) icms_dc=0 , 0.1063280 secs] [Times: user=0.61 sys=0.00, real=0.11 secs] 
    14506.980: [GC 14506.980: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   42002904 bytes,   42002904 total
    - age   2:   35733928 bytes,   77736832 total
    : 1764543K->96136K(1887488K), 0.0982790 secs] 4864371K->3195964K(6081792K) icms_dc=0 , 0.0988960 secs] [Times: user=0.53 sys=0.01, real=0.10 secs] 
    14544.285: [GC 14544.286: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   26159736 bytes,   26159736 total
    - age   2:   37842840 bytes,   64002576 total
    - age   3:   33192784 bytes,   97195360 total
    : 1773960K->130799K(1887488K), 0.1208590 secs] 4873788K->3230628K(6081792K) icms_dc=0 , 0.1215900 secs] [Times: user=0.59 sys=0.02, real=0.13 secs] 
    14589.266: [GC 14589.266: [ParNew
    Desired survivor size 107347968 bytes, new threshold 4 (max 8)
    - age   1:   28010360 bytes,   28010360 total
    - age   2:   21136704 bytes,   49147064 total
    - age   3:   35081376 bytes,   84228440 total
    - age   4:   32468056 bytes,  116696496 total
    : 1808623K->148284K(1887488K), 0.1423150 secs] 4908452K->3248112K(6081792K) icms_dc=0 , 0.1429440 secs] [Times: user=0.70 sys=0.02, real=0.14 secs] 
    14630.947: [GC 14630.947: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   28248240 bytes,   28248240 total
    - age   2:   20712320 bytes,   48960560 total
    - age   3:   18217168 bytes,   67177728 total
    - age   4:   34834832 bytes,  102012560 total
    : 1826108K->140347K(1887488K), 0.1784680 secs] 4925936K->3275469K(6081792K) icms_dc=0 , 0.1790920 secs] [Times: user=0.98 sys=0.03, real=0.18 secs] 
    14664.779: [GC 14664.779: [ParNew
    Desired survivor size 107347968 bytes, new threshold 5 (max 8)
    - age   1:   25841000 bytes,   25841000 total
    - age   2:   22264960 bytes,   48105960 total
    - age   3:   17730104 bytes,   65836064 total
    - age   4:   17988048 bytes,   83824112 total
    - age   5:   34739384 bytes,  118563496 total
    : 1818171K->147603K(1887488K), 0.1714160 secs] 4953293K->3282725K(6081792K) icms_dc=0 , 0.1720530 secs] [Times: user=0.82 sys=0.11, real=0.17 secs] 
    14702.488: [GC 14702.489: [ParNew
    Desired survivor size 107347968 bytes, new threshold 8 (max 8)
    - age   1:   26887368 bytes,   26887368 total
    - age   2:   21403352 bytes,   48290720 total
    - age   3:   18732224 bytes,   67022944 total
    - age   4:   17640576 bytes,   84663520 total
    - age   5:   17942952 bytes,  102606472 total
    : 1825427K->142695K(1887488K), 0.2118320 secs] 4960549K->3312168K(6081792K) icms_dc=0 , 0.2124630 secs] [Times: user=1.13 sys=0.14, real=0.21 secs] 

我的目标是: 我想限制Tenured的最小值,我正在服务请求并期望超过一定数量的共享对象,其他所有对象仅对手头的请求有用。因此,通过使用一个大的NewSize和一个增加的TenuringThreshold,并希望没有这些单个服务对象.- / p>

以下是支持我的策略:
-Xms = 6G
-Xmx = 6G
-XX:NewSize = 2G //大空间,以免ParNew经常发生,让对象有时间到期 -XX:MaxTenuringThreshold = 8 //更多地限制任期 -XX:SurvivorRatio = 7 //基于示例 -XX:CMSInitiatingOccupancyFraction = 60
//以防止促销分配导致的完整GC失败 -XX:+ UseCMSInitiatingOccupancyOnly
//根据示例使用上面的那个

MaxPermSize = 1G和“-Dsun.reflect.inflationThreshold = 0”与另一个我宁愿分开的问题有关。

“ - XX:+ CMSClassUnloadingEnabled”和“-XX:+ CMSPermGenSweepingEnabled”是因为grails严重依赖并且额外的类用于闭包和反射

-XX:+ CMSIncrementalMode是一项没有取得多大成功的实验

5 个答案:

答案 0 :(得分:11)

发布的日志片段显示您有大量的对象活动时间> 320秒(每个年轻集合大约40秒,对象在促销前通过8个集合生存)。剩下的物体然后流入终身,最终你击中了一个显然意外的完整gc,实际上并没有收集太多。

3453285K->3099828K(4194304K)

即。当你被触发时,你有一个4G天赋,大约82%满(3453285/4194304),经过13长时间后大约74%。

这意味着需要花费13秒来收集~350M的总计,这在6G堆的情况下并不是很多。

这基本上意味着你的堆不够大,或者更可能是你有内存泄漏。这样的泄漏对于CMS来说是一件可怕的事情,因为并发终身收集是一个非紧凑的事件,这意味着终身是一个免费列表的集合,这意味着碎片可能是CMS的一个大问题,这意味着您对终身的利用变得越来越低效,意味着促销失败事件的概率增加(尽管如果这是一个事件,那么我希望看到一条日志消息说明),因为它想要推广(或认为它需要推广)X MB到终身但它没有(连续的)免费列表> = X MB可用。这会触发意外的终端收集,这是一个非远程并发的STW事件。如果你实际上有很少的东西可以收集(就像你一样),那么毫无疑问你会坐在你的拇指上。

一些一般性的指示,在很大程度上重申弗拉基米尔·西特尼托夫所说的......

  • 在多核盒子上使用iCMS是没有意义的(除非你有很多的JVM或在该盒子上运行的其他进程,以致JVM真的缺少CPU)因此删除此开关
  • 你的年轻收藏品不必要地长,因为在每个收藏品的幸存者空间之间复制相对大量的记忆会产生影响,150-200ms是一个非常庞大的ParNew集合
    • 对年轻人问题的正确答案取决于分配行为的真正含义(例如,或许你最好早点放弃,减少碎片对终身收藏的影响或者你可能会更好更大规模的新一代,减少了年轻人的收集频率,以便减少对象的推广,从而减少对终身的流失。

有些问题......

  • 最终是OoM还是恢复?
  • 是处于稳定状态的应用程序(在远远超出启动的某个时刻受到一致的负载)在此日志片段中还是处于压力之下?

答案 1 :(得分:8)

  

我正在处理请求并期望超出一定数量的共享对象,每个其他对象仅对手头的请求有用。   这就是理论,但任何类型的缓存都很容易使该假设无效并创建超出请求的对象。

正如其他人所指出的那样,你的巨大年轻一代和延长的任期似乎都不起作用。

您应该分析您的应用程序并分析对象的年龄分布。我非常相信Grails会缓存超出请求范围的所有事情,这就是泄漏到旧版本的内容。

你真正想要的是牺牲年轻一代的暂停时间(对于2GB的年轻一代)来推迟不可避免的 - 一个6GB的旧系列。这并不是你在那里做的一个很好的权衡。

相反,您可能应该针对更好的年轻时间暂停时间并允许CMS消耗更多的CPU时间:更多的相位GC线程(不记得该选项),更高GCTimeRatio,一个{ {1}}> MaxGCPauseMillis要对次要收藏品施加压力,让他们达到暂停目标,而不必调整大小以适应主要的收藏限制。

为了让主要的GC减少痛苦,你可能想要阅读:http://blog.ragozin.info/2012/03/secret-hotspot-option-improving-gc.html(这个补丁应该在j7u4中)。还应启用MaxGCMinorPauseMillis,不确定这是否为默认值。

替代方案:使用G1GC

就我个人而言,由于一些非常大的类似LRU的工作负载,然后回归到一个大型的世界各地的集合,我经历了一些非常糟糕的经历,G1GC正在努力进入一个角落,远远超过CMS遇到的并发模式故障相同的工作量。

但对于其他工作负载(例如你的工作负载),它实际上可以完成工作并逐步收集旧代,同时还可以压缩并避免任何大的暂停。

如果你还没有试一试。再次,在你这样做之前更新到最新的java7,G1仍然存在一些启发式问题,他们正试图解决这个问题。

编辑:自从我写完这个答案以来,Oracle已经改进了G1GC的启发式和一些瓶颈。现在绝对值得一试。

另一种选择:吞吐量收集器

因为你已经在为2GB的年轻人使用并行收集器并且在200ms的暂停时间内逃脱了...为什么不在你的6G堆上尝试并行的旧收发器呢?它可能需要少于你用CMS看到的10s +主要收藏品。每当CMS遇到其中一种失败模式时,它都会执行单线程,停止世界的收集。

答案 2 :(得分:4)

请描述Tomcat可以使用多少CPU? 4?

你使用的是什么java版本? (> 1.6.0u23?)

0)在Full GC输出中,它看起来肯定会达到内存限制:即使在完全gc之后,仍然有3099828K的已用内存(4194304K中)。 当你内存不足时,没有办法阻止Full GC。

您的应用需要3.1Gb工作集吗? 那是3.1Gb的非垃圾内存!

如果需要,可以增加-Xmx / -Xms。 否则,是时候收集和分析堆转储以识别内存耗尽。

解决3Gb工作集的问题后,您可能会发现以下建议有用: 从我的角度来看,常规(非增量)CMS模式和减少NewSize值得尝试。

1)当CMS线程将CPU交给其他线程时,增量模式针对单个cpu机器。

如果您有一些备用CPU(例如,您正在运行多核计算机),最好在后台执行GC而不会产生效果。

因此我建议删除-XX:+ CMSIncrementalMode。

2)-XX:CMSInitiatingOccupancyFraction = 60告诉CMS在OLD gen已满60%后启动后台GC。

如果堆中有垃圾,并且CMS无法跟上它,那么降低CMSInitiatingOccupancyFraction是有意义的。 例如,-XX:CMSInitiatingOccupancyFraction = 30,因此当旧的gen为30%时,CMS将启动并发收集。 目前很难判断是否是这种情况,因为你的堆中没有垃圾。

3)看起来“延长任期”并没有帮助 - 即使在7-8次任期之后,物体也不会消失。我建议减少SurvivorRatio(例如,SurvivorRatio = 2,或者只是删除选项并坚持默认)。 这将减少任期,从而减少次要gc暂停。

4)-XX:NewSize = 2G。你为NewSize尝试了较低的值吗? 说,NewSize = 512m。这应该可以减少次要的gc暂停,并使促销变得年轻 - >旧的不那么大,简化了CMS的工作。

答案 3 :(得分:3)

你的幸存者数量并没有减少很多,如果有的话 - 理想情况下它们应该急剧下降,因为你只想让少数物体存活足够长的时间才能到达老一代。

这表明许多对象的生存时间相对较长 - 例如,当您有许多打开的连接,线程等无法快速处理时,就会发生这种情况。

(您是否有任何选项可以更改应用程序,或者您只能修改GC设置?可能还有Tomcat设置会产生影响......)

答案 4 :(得分:0)

以下是我对4核Linux盒的设置。

根据我的经验,您可以调整-XX:NewSize -XX:MaxNewSize -XX:GCTimeRatio以实现高吞吐量和低延迟。

-server
-Xms2048m
-Xmx2048m
-Dsun.rmi.dgc.client.gcInterval = 86400000
-Dsun.rmi.dgc.server.gcInterval = 86400000
-XX:+ AggressiveOpts
-XX:GCTimeRatio = 20
-XX:+ UseParNewGC
-XX:ParallelGCThreads = 4
-XX:+ CMSParallelRemarkEnabled
-XX:ParallelCMSThreads = 2
-XX:+ CMSScavengeBeforeRemark
-XX:+ UseConcMarkSweepGC
-XX:+ UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction = 50
-XX:NewSize = 512m
-XX:MaxNewSize = 512m
-XX:PermSize = 256m
-XX:MaxPermSize = 256m
-XX:SurvivorRatio = 90
-XX:TargetSurvivorRatio = 90
-XX:MaxTenuringThreshold = 15
-XX:MaxGCMinorPauseMillis = 1
-XX:MaxGCPauseMillis = 5
-XX:+ PrintGCDateStamps
-XX:+ PrintGCDetails
-XX:+ PrintTenuringDistribution
-Xloggc:./ logs / gc.log