请教 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 吧……
Global site tag (gtag.js) - Google Analytics