请教 JVM GC 参数调优的问题
Anson0370
2014-03-20
一个 web 应用,情况是经常有 1M 左右大小的字符串产生(远程调用回来的一些报文),每次 YGC 都会有一些进 old 。
在高峰期 old 增长比较快,大概每 5、6 分钟就来一次 FGC ,每次耗时 2s 多。 但每次 FGC 后 old 都能被回收的差不多。 一看就有问题的 JVM 启动参数: 引用 -server -Xss128k -Xms3500m -Xmx3500m -XX:MaxNewSize=256m -XX:MaxPermSize=512m -XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:/tmp/logs/gc.log -XX:+PrintGCTimeStamps -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
jmap -heap 的一个瞬时情况: 引用 using thread-local object allocation.
Parallel GC with 48 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 3670016000 (3500.0MB) NewSize = 2686976 (2.5625MB) MaxNewSize = 268435456 (256.0MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 536870912 (512.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 152436736 (145.375MB) used = 137799720 (131.41605377197266MB) free = 14637016 (13.958946228027344MB) 90.3979733599124% used From Space: capacity = 58589184 (55.875MB) used = 27553344 (26.27691650390625MB) free = 31035840 (29.59808349609375MB) 47.02803848573826% used To Space: capacity = 57409536 (54.75MB) used = 0 (0.0MB) free = 57409536 (54.75MB) 0.0% used PS Old Generation capacity = 3401580544 (3244.0MB) used = 2920355048 (2785.0676040649414MB) free = 481225496 (458.9323959350586MB) 85.85288545206355% used PS Perm Generation capacity = 278790144 (265.875MB) used = 190314448 (181.4980010986328MB) free = 88475696 (84.37699890136719MB) 68.26441038030383% used CPU 信息 引用 cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
48 Intel(R) Xeon(R) CPU E7540 @ 2.00GHz JDK 版本 引用 1.6.0_11-b03
应用直接跑在物理机上,不是虚拟机,操作系统 引用 Red Hat Enterprise Linux Server release 5.5
部分 FGC 的日志(YGC 的比较多,就没放进来) 引用 43279.075: [Full GC [PSYoungGen: 7389K->0K(248960K)] [PSOldGen: 3316049K->621711K(3321856K)] 3323438K->621711K(3570816K) [PSPermGen: 160372K->160372K(321280K)], 2.3098470 secs] [Times: user=2.30 sys=0.01, real=2.31 secs]
44898.068: [Full GC [PSYoungGen: 5907K->0K(234112K)] [PSOldGen: 3317090K->676247K(3321856K)] 3322998K->676247K(3555968K) [PSPermGen: 167521K->167521K(366464K)], 2.3110800 secs] [Times: user=2.31 sys=0.00, real=2.31 secs] 46014.258: [Full GC [PSYoungGen: 25367K->0K(222016K)] [PSOldGen: 3314496K->707444K(3321856K)] 3339863K->707444K(3543872K) [PSPermGen: 171583K->171583K(359168K)], 2.3204730 secs] [Times: user=2.32 sys=0.00, real=2.32 secs] 46915.333: [Full GC [PSYoungGen: 13718K->0K(225856K)] [PSOldGen: 3319297K->566283K(3321856K)] 3333015K->566283K(3547712K) [PSPermGen: 174917K->172803K(344832K)], 2.5155390 secs] [Times: user=2.51 sys=0.00, real=2.52 secs] 47799.685: [Full GC [PSYoungGen: 204341K->0K(226944K)] [PSOldGen: 3311190K->780553K(3321856K)] 3515532K->780553K(3548800K) [PSPermGen: 177801K->177801K(334912K)], 2.2714570 secs] [Times: user=2.27 sys=0.01, real=2.27 secs] 48393.483: [Full GC [PSYoungGen: 27670K->0K(212928K)] [PSOldGen: 3313918K->744557K(3321856K)] 3341588K->744557K(3534784K) [PSPermGen: 179630K->179630K(322432K)], 2.3096170 secs] [Times: user=2.31 sys=0.01, real=2.31 secs] 49111.000: [Full GC [PSYoungGen: 190513K->0K(210432K)] [PSOldGen: 3319876K->756815K(3321856K)] 3510390K->756815K(3532288K) [PSPermGen: 181377K->181377K(309504K)], 2.3270380 secs] [Times: user=2.33 sys=0.00, real=2.33 secs] 49512.533: [Full GC [PSYoungGen: 5272K->0K(196096K)] [PSOldGen: 3301429K->620107K(3321856K)] 3306702K->620107K(3517952K) [PSPermGen: 182789K->182408K(295488K)], 2.4052600 secs] [Times: user=2.40 sys=0.00, real=2.41 secs] ============= 分隔线 ================ 就我的理解,我以为只要把 young 和 survivor 搞大,让更多的对象(前文提到的大字符串)能在 YGC 时被干掉,FGC 应该就会降低。 所以我想着把参数改成这样: 引用 -server -Xms3500m -Xmx3500m -Xmn1000m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:SurvivorRatio=4 -XX:+PrintGCDetails -Xloggc:/tmp/logs/gc.log -XX:+PrintGCTimeStamps
但是我查到资料说 -server 时默认使用的 Parallel GC 默认打开了 UseAdaptiveSizePolicy ,这个选项会自动调整 young 和 s0 s1 的大小。我不了解这个自动调整的具体原则是怎么样的,是保留好还是关闭好,如果自动调整似乎我的设置就不会起作用。 以及是否该使用 CMS ? 总之就是希望 FGC 能变少变快(应用层面的调整现在做不了,只能寄希望于 JVM 参数了)。 |
|
RednaxelaFX
2014-03-20
48核!好高端的机器!
然而为啥GC堆才那么小 =_= 如果要对ParallelScavenge做精确调优的话,需要-XX:-UseAdaptiveSizePolicy来关闭动态调整GC堆各空间大小的行为。 SurvivorRatio可以调小一点来调大survivor space的大小,并且TargetSurvivorRatio可能可以调大一点来延迟对象晋升到old gen的时机。 另外JDK6u11实在太老了。啊能升级到至少JDK6u32以上? 实在不行再试CMS |
|
Anson0370
2014-03-20
电信有钱能搞啊……48核随便上!JDK 升级也提过……但没被他们实施
所以我果然还是需要 -UseAdaptiveSizePolicy ,那么就把 SurvivorRatio 弄成 3 吧,然后 TargetSurvivorRatio 有经验值可参考么?80 如何? |
|
RednaxelaFX
2014-03-20
Anson0370 写道 电信有钱能搞啊……48核随便上!
擦,太牛逼了 Anson0370 写道 JDK 升级也提过……但没被他们实施
这怎么行。6u11太不靠谱了。要我举几个bug来帮你说服他们么? Anson0370 写道 所以我果然还是需要 -UseAdaptiveSizePolicy ,那么就把 SurvivorRatio 弄成 3 吧,然后 TargetSurvivorRatio 有经验值可参考么?80 如何?
SurvivorRatio=3有点激进…如果能试很多次的话,从默认的8一直往下降来实验会比较好。 TargetSurvivorRatio默认是50。这个也是,如果能实验多次的话,最好从50开始逐渐上升。我以前见过到75的,再高有点危险… |
|
Anson0370
2014-03-20
RednaxelaFX 写道 SurvivorRatio=3有点激进…如果能试很多次的话,从默认的8一直往下降来实验会比较好。
TargetSurvivorRatio默认是50。这个也是,如果能实验多次的话,最好从50开始逐渐上升。我以前见过到75的,再高有点危险… 他们 3 台机器,我打算让他们只改一台试试。那么就 SurvivorRatio=4 TargetSurvivorRatio=70 吧…… |