JVM微调

 上页

高吞吐量调整

  1. UseParallelGC 和UseParNewGC等高吞吐量配合参数:
  1. -XX:+UseAdaptiveSizePolicy
  2. -XX:MaxGCPauseMillis=… (i.e. 100)
  3. -XX:GCTimeRatio=… (i.e. 19)

UseAdaptiveSizePolicy

  1. 当使用-XX:+UseParallelGC 缺省策略加载,XX:+UseAdaptiveSizePolicy。
  2. 主要调整下面参数,在暂停和吞吐量之间取得一个平衡:
  3. 一个合适的最大GC暂停值
  4. 一个合适的应用程序吞吐量值
  5. 最小化实现路径。

UseAdaptiveSizePolicy 策略路径

  1. 如果GC暂停时间大于目标暂停时间(-XX:MaxGCPauseMillis=nnn ),降低新生代大小以匹配目标暂停时间。
  2. 如果暂停时间合适,考虑应用的吞吐量,通过增大新生代的大小满足吞吐量。
  3. 如果暂停时间和吞吐量两个目标都满足,新生代大小降低以节约成本路径。

UseAdaptiveSizePolicy

  1. -XX:MaxGCPauseMillis=nnn :不能设置过小,会阻碍吞吐量,如果不设置,暂停时间依赖heap中活动数据量。
  1. -XX:GCTimeRatio=nnn 不超过应用运行时间的1 / (1 + nnn) 用在垃圾回收上。缺省99。垃圾回收时间不应该超过整体时间的1%

JVM微调调试方法

  1. 配置JVM的JAVA_OPTS参数 –verbosegc
  2. 观察Full GC的信息输出:
  3. [Full GC $before->$after($total), $time secs]
  4. Full GC太频繁,应用暂停,响应时间受影响。
  5. 克服GC太频繁方法:
  6. 1. 增大内存。增大年轻代的内存
  7. 2.使用LRU等缓存,限制大量对象创建。
  8. 3. 64位下压缩对象头。
  9. 消灭Full GC:-XX:+PrintGCDetails 无Full GC输出

内存大小影响

  1. 大内存:

       1. 降低GC执行次数。
        2.增加每次GC执行的时间。

  1. 小内存:

        1.增加了GC执行次数
         2.降低每次GC执行的时间。

如果Full GC能够在1秒内完成,10G也是合适的。


Jstat 监视微调

  1. jstat -gcutil 21891 250 7
  2. 21891是Java的pid, 250表示间隔几秒  7表示采样7次
  3. S0      S1     E      O    P      YGC  YGCT FGC FGCT   GCT
    12.44 0.00 27.20 9.49 96.70 78 0.176 5 0.495 0.672
    12.44 0.00 62.16 9.49 96.70 78 0.176 5 0.495 0.672
    12.44 0.00 83.97 9.49 96.70 78 0.176 5 0.495 0.672
    0.00 7.74 0.00 9.51 96.70 79 0.177 5 0.495 0.673
    0.00 7.74 23.37 9.51 96.70 79 0.177 5 0.495 0.673
    0.00 7.74 43.82 9.51 96.70 79 0.177 5 0.495 0.673
    0.00 7.74 58.11 9.51 96.71 79 0.177 5 0.495 0.673
  4. Minor GC :YGC年轻代GC发生了78次,YGCT是GC发生的时间累计0.176。
  5. FULL GC发生了5次,累计0.495, 每次是0.495/5
  6. http://www.cubrid.org/blog/dev-platform/how-to-monitor-java-garbage-collection/
  7. 如果GC执行时间在一秒以上,需要GC微调,如果在0.1-0.3之间则不需要

需要微调的案例

  1. Full GC超过一秒,需要微调。
  2. Minor GC正常

 

jvm4


 

微调前检查内存大小分配

  1. jstat –gccapacity
  2. NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
  3. 212992.0 212992.0 212992.0 21248.0 21248.0 170496.0 1884160.0 1884160.0 1884160.0 1884160.0 262144.0 262144.0 262144.0 262144.0 54 5
  4. 新生代是 212,992 KB,老生代是1,884,160 KB
  5. 新生代:老生代是1:9, 调整NewRatio
  6. NewRatio=2
  7. NewRatio=3
  8. NewRatio=4
  9. 如果其中一个设置没有FULL GC发生,就是合适新生代和老生代的大小。
  1. 随着新生代内存减小,其GC时间缩短:
  2. NewRatio=2: 45 ms
  3. NewRatio=3: 34 ms
  4. NewRatio=4: 30 ms
  5. 内存输出结构:
  6. S0 S1 E O P YGC YGCT FGC FGCT GCT
  7. 8.61 0.00 30.67 24.62 22.38 2424 30.219 0 0.000 30.219
  8. 年轻代发生了2424次,而FullGC没有一次发生,存在大量临时对象都是新生代毁灭。

Jstat参数说明

jvm jstat参数

 


JVM优化参数

  1. JAVA_OPTS="$JAVA_OPTS  -verbose:gc  -XX:+PrintGCDetails -XX:+PrintTenuringDistribution  -Xloggc:/home/jdon/jdongc.log  -server -Xms1536m -Xmx1664m -XX:NewSize=768m  -XX:MaxNewSize=896m -XX:+UseAdaptiveGCBoundary  -XX:MaxGCPauseMillis=250 -XX:+UseAdaptiveSizePolicy  -XX:+DisableExplicitGC -XX:ParallelGCThreads=4 -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode  -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSClassUnloadingEnabled
  2. 最大新生代GC暂停时间是250毫秒,在这个基础上JVM自动调整尽量满足吞吐量。
  3. [GC 2016.468: [ASParNew: 686991K->42743K(711316K), 0.1310080 secs] 713706K->74888K(1422668K) icms_dc=0 , 0.1324500 secs]
  4. S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT  
  5.   0.00  64.80  93.53   4.52  66.34      7    0.619     7    2.381    3.000
jvm优化

如果响应时间还是不够快?

  1. 响应延迟和吞吐量是一对矛盾,而吞吐量主要标志是内存大小。
  1. 降低NewSize大小, 降低survivor空间。
  2. 降低进入老生代reduce的门槛,因为缓存Hold住大量长生命对象,让这些对象进口进入老生代。而老生代的CMS很少暂停。

 

CMS

  1. CMS并不进行内存压实compact,所以,会导致碎片。而碎片也会导致暂停。
  1. Apache Cassandra使用 slab allocator。
  2. 每个Slab是2M;
  3. 用compare-and-set拷贝他们。
  4. 三天

G1 vs CMS vs Parallel GC

  三个垃圾回收机制的比较,语法如下:

  • -XX:+UseParallelOldGC
  • -XX:+UseConcMarkSweepGC
  • -XX:+UseG1GC

  使用GCViewer观察,结果如下 单位是毫秒:


Parallel CMS G1
Total GC pauses 20 930 18 870 62 000
Max GC pause 721 64 50

并行GC ( - XX:+ UseParallelOldGC ) 。在30多分钟的测试时间内,用并行收集器 GC暂停花了接近21秒。最长停顿了721毫秒。因此,我们以此为基准: GC降低了吞吐量为总运行时间的1.1 %。最坏情况下的延迟为721ms 。

CMS ( - XX:+ UseConcMarkSweepGC ) 同样30分钟,因为GC我们失去了不到19秒 。相比并行GC吞吐量明智的。延迟另一方面已显著改善 - 最坏情况下的延迟时间减少10倍以上!来自GC的最大暂停时间我们现在面临的只是64ms。

最闪亮的GC算法 - G1 ( - XX:+ UseG1GC ) 。在同样的测试,,我们看到的结果吞吐量问题比较严重。这一次,我们的应用程序花费超过一分钟等待GC来完成。比较这与CMS中的开销只有1% ,我们现在面对接近的吞吐量3.5 %的效果。但如果你真的不关心的吞吐量,而是想挤出最后那么一点延迟 - 比CMS提高20%左右 - 用G1看到的最长GC暂停服用仅50毫秒。

结论:CMS仍然是最好的“默认”选项。 G1的吞吐量仍然差那么多,得到的延迟通常是不值得的。

JVM推荐设置

Heap size Total GC pauses GC暂停 Throughput吞吐量
-Xmx 300m 207.48s 92.25%
-Xmx 384m 54.13s 97.97%
-Xmx 720m 20.52s 99.11%
-Xmx 1,440m *11.37s *99.55%

JVM有关垃圾回收机制的配置

下页

 

生产环节下JVM运营监测

多线程

同步或锁

性能测试

性能调优

高性能

可伸缩性

JVM专题讨论