一尘不染

GC调整-防止完全GC

java

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

14359.317:[完整GC 14359.317:[CMS:3453285K- > 3099828K(4194304K),13.1778420秒]
4506618K-> 3099828K(6081792K),[CMS彼尔姆:261951K-> 181304K(264372K)] icms_dc =
0,13.1786310秒] [Times :user = 13.15 sys = 0.04,real = 13.18 secs]

我的VM PARAMS如下:
-Xms = 6G
-Xmx = 6G
-XX:MaxPermSize参数= 1G
-XX:新尺寸= 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-
D =

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

我瞄准的策略是:我希望将Tenured的情况限制到最小,我正在处理请求,并希望除了一定数量的共享对象外,其他所有对象仅对当前的请求有用。因此,通过使用较大的NewSize和增加的TenuringThreshold,并希望这些单个服务对象都不会停留在周围。

以下是支持我的策略的地方:
-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是一个没有成功的实验


阅读 215

收藏
2020-12-03

共1个答案

一尘不染

日志片段显示您拥有大量可存活超过320秒的对象(每个年轻集合大约40
s,并且在升级之前,对象可以通过8个集合生存)。剩余的对象随后流失到永久使用权,最终您遇到了一个明显意外的完整gc,实际上并没有收集太多。

3453285K->3099828K(4194304K)

也就是说,您有一个4G的使用权,在触发时使用率约为〜82%(3453285/4194304),而在13秒钟后则约为〜74%。

这意味着要花13秒钟才能收集到约350M的总数,这在6G堆的情况下是不多的。

这基本上意味着您的堆不够大,或者更有可能发生内存泄漏。像这样的泄漏对于CMS来说是一个可怕的事情,因为并发的权属集合是非压缩事件,这意味着权属是自由列表的集合,这意味着碎片对于CMS可能是个大问题,这意味着权能的使用效率越来越低,意味着升级失败事件的可能性增加(尽管如果是这样的事件,那么我希望看到一条日志消息说),因为它想将X
MB升级为(或认为需要升级)X终身制但没有可用的(连续的)空闲列表,该列表> = X MB。这将触发意外的永久集合,这是一个不是远程并发的STW事件。

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

  • 在多核计算机上使用iCMS没有任何意义(除非您在该计算机上运行了 许多 JVM或其他进程,使得JVM确实缺乏CPU),因此请删除此开关
  • 由于每个幸存者空间之间会在每个集合之间复制相对大量的内存,因此您的年轻集合会不必要地长,150-200ms是一个非常庞大的ParNew集合
    • 对年轻一代问题的正确答案取决于分配行为的真正含义(例如,也许您会更好地尽早使用权,并减少碎片化对长期收藏的影响,或者也许您会拥有更多新的更好的选择并减少年轻一代的收集频率,这样可以减少推广的对象,从而使流失到使用年限的可能性降到最低。

一些问题…

  • 最终会达到OoM还是恢复?
  • 在此日志摘要中,应用程序处于稳定状态(在启动后的某个时刻承受一致的负载)还是处于压力之下?
2020-12-03