专栏首页Linyb极客之路JVM内存模型和性能优化之JVM微调(中篇)

JVM内存模型和性能优化之JVM微调(中篇)

高吞吐量调整

  1. UseParallelGC 和UseParNewGC等高吞吐量配合参数:
  2. -XX:+UseAdaptiveSizePolicy
  3. -XX:MaxGCPauseMillis=… (i.e. 100)
  4. -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中活动数据量。

2、-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执行的时间。

2、小内存:

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

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


Jstat 监视微调

jstat -gcutil 21891 250 7
21891是Java的pid, 250表示间隔几秒  7表示采样7次
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
Minor GC :YGC年轻代GC发生了78次,YGCT是GC发生的时间累计0.176。
FULL GC发生了5次,累计0.495, 每次是0.495/5
http://www.cubrid.org/blog/dev-platform/how-to-monitor-java-garbage-collection/
如果GC执行时间在一秒以上,需要GC微调,如果在0.1-0.3之间则不需要

需要微调的案例

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

微调前检查内存大小分配

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

Jstat参数说明


JVM优化参数

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
最大新生代GC暂停时间是250毫秒,在这个基础上JVM自动调整尽量满足吞吐量。
[GC 2016.468: [ASParNew: 686991K->42743K(711316K), 0.1310080 secs] 713706K->74888K(1422668K) icms_dc=0 , 0.1324500 secs]
S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT  
  0.00  64.80  93.53   4.52  66.34      7    0.619     7    2.381    3.000

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

1、响应延迟和吞吐量是一对矛盾,而吞吐量主要标志是内存大小。

2、降低NewSize大小, 降低survivor空间。

3、降低进入老生代reduce的门槛,因为缓存Hold住大量长生命对象,让这些对象进口进入老生代。而老生代的CMS很少暂停。

CMS

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吞吐量

-Xmx300m

207.48s

92.25%

-Xmx384m

54.13s

97.97%

-Xmx720m

20.52s

99.11%

-Xmx1,440m

*11.37s

*99.55%

本文分享自微信公众号 - Linyb极客之路(gh_c420b2cf6b47)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java开发中的问题排查,性能调优,先学会阅读GC日志

    阅读GC日志是处理Java虚拟机内存问题的基础技能,它只是一些人为确定的规则,没有太多技术含量。

    lyb-geek
  • 这 17 个 JVM 参数,高级 Java 必须掌握!

    大家都知道,jvm在启动的时候,会执行默认的一些参数。一般情况下,这些设置的默认参数应对一些平常的项目也够用了。但是如果项目特别大了,需要增加一下堆内存的大小、...

    lyb-geek
  • Java性能调优最强实践,让系统飞起来~

    Java 应用性能的瓶颈点非常多,比如磁盘、内存、网络 I/O 等系统因素,Java 应用代码,JVM GC,数据库,缓存等。笔者根据个人经验,将 Java 性...

    lyb-geek
  • JVM性能调优-探索堆内存到底是怎么分配

    新⽣代 GC (Minor GC):指发⽣在新⽣代的垃圾收集动作,因为 Java 对象⼤多都具备朝⽣夕灭的特性,所以 Minor GC ⾮常频繁,⼀般回收速度⽼...

    cwl_java
  • 从ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection

    在阅读这篇文章:Announcing Net Core 3 Preview3的时候,我看到了这样一个特性:

    ShenduCC
  • 老公:怎么排查堆内存溢出啊?

    上次给老公们说过了死循环cpu飙高的排查过程,今天就带着老公们看看堆内存溢出我们一般怎么排查的。

    敖丙
  • [三步法] 可视化分析定位线上 JVM 问题

    前提是线上 JVM 配置了以下参数: [题外话:JDK 版本 1.6,现在大部分互联网企业应用系统应该是 1.8 以上了吧 ]

    IT技术小咖
  • 程序员如何优化 Java GC

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作。

    黄泽杰
  • Full GC 和 Minor GC,傻傻分不清楚

    大家可能见到过很多的 GC 名词,比如:Minor GC、Young GC、Full GC、Old GC、Major GC、Mixed GC。

    武培轩
  • JVM系列第10讲:垃圾回收的几种类型

    我们经常会听到许多垃圾回收的术语,例如:Minor GC、Major GC、Young GC、Old GC、Full GC、Stop-The-World 等。但...

    陈树义

扫码关注云+社区

领取腾讯云代金券