常用JVM垃圾收集器GC调优

常⽤JVM垃圾收集器GC调优
GC调优概述
对JVM垃圾收集器进⾏调优之前,⼀定要先了解JVM内存结构、各个垃圾收集器的特点、常⽤的JVM参数、GC⽇志理解、GC⽇志可视化(GCeasy,GCViewer)等,因为这些东西不了解的话,是没法进⾏调优的。JVM调优是⼀个不断调整的过程,不能指望着⼀蹴⽽就。要不断调整相关参数,观察结果进⾏对⽐分析。还有就是,不同的垃圾收集器的JVM参数是不⼀样的,所以具体的GC调优要根据不同的收集器做调整。
另外说⼀点,其实⼀般的Java程序是不需要调优的,除⾮你的应⽤程序并发访问量⽐较⾼。⼀般出现问题,都是由代码操作不当引起的,所以⼤部分情况下分析代码多过分析GC进⾏调优,我们在写代码的时候⼀定要注意优化,避免内存泄露。
GC调优的⽬标
1、最⼤暂停时间⽬标(Maximum Pause Time Goal)
暂停时间是垃圾收集器停⽌应⽤程序并恢复不再使⽤的空间的持续时间。最⼤暂停时间⽬标的⽬的是限制这些暂停中的最长时间。垃圾回收器会维持平均的暂停时间和该平均值的⽅差。平均值是从执⾏开始
时获取的,但经过加权后,最近的暂停次数会增加。如果平均时间加上暂停时间的⽅差⼤于最⼤暂停时间⽬标,则垃圾回收器认为未达到⽬标。
最⼤暂停时间⽬标是通过命令⾏选项指定的-XX:MaxGCPauseMillis=<nnn>。这被解释为垃圾收集器的提⽰,要求暂停时间为<nnn>毫秒或更短。垃圾收集器将调整Java堆⼤⼩和与垃圾收集相关的其他参数,以使垃圾收集暂停时间短于<nnn>毫秒。默认情况下,没有最⼤暂停时间⽬标。这些调整可能导致垃圾回收器更频繁地发⽣,从⽽降低了应⽤程序的整体吞吐量。垃圾收集器会尝试在吞吐量⽬标之前达到任何暂停时间⽬标。但是,在某些情况下,⽆法达到所需的暂停时间⽬标。
2、吞吐量⽬标(Throughput Goal)
吞吐量⽬标是根据收集垃圾所花费的时间和垃圾收集之外所花费的时间(称为应⽤时间)来衡量的。⽬标由命令⾏选项指定-
XX:GCTimeRatio=<nnn>。垃圾收集时间与应⽤程序时间的⽐率为1 /(1 + <nnn>)。例如,-XX:GCTimeRatio=19将垃圾收集⽬标设置为⽬标1/20或总时间的5%。
垃圾收集所花费的时间是年轻代(young区)和⽼年代(Old区)收集的总时间。如果没有达到吞吐量⽬标,那么将增加世代的⼤⼩,以增加应⽤程序在集合之间运⾏的时间。
折叠耳机
灭蚊机3、⾜迹⽬标(Footprint Goal)
如果已满⾜吞吐量和最⼤暂停时间⽬标,则垃圾收集器会减⼩堆的⼤⼩,直到⽆法满⾜其中⼀个⽬标(始终是吞吐量⽬标)。然后解决未实现的⽬标。
通俗来说,实现这两个⽬标:1.将转移到⽼年代的对象数量降低到最⼩;2.减少full GC的执⾏次数和时间。说⼀千道⼀万,GC调优的⽬的就是提⾼应⽤程序吞吐量、降低GC暂停时间。
GC调优准则
拖曳声纳除⾮您知道需要的堆⼤于默认的最⼤堆⼤⼩,否则不要为堆选择最⼤值。
如果堆增长到最⼤⼤⼩,并且⽆法满⾜吞吐量⽬标,则最⼤堆⼤⼩对于吞吐量⽬标⽽⾔太⼩。将最⼤堆⼤⼩设置为接近平台上总物理内存(不能让OS使⽤swap内存)。再次执⾏该应⽤程序。如果仍然没有达到吞吐量⽬标,那么对于平台上的可⽤内存来说,应⽤程序时间⽬标太⾼了。
如果可以满⾜吞吐量⽬标,但暂停时间太长,则选择最⼤暂停时间⽬标。选择最⼤暂停时间⽬标可能意味着您的吞吐量⽬标将⽆法实现,因此请选择对应⽤程序可接受的折衷值。
简单来说如下所⽰:
除⾮确定,否则不要设置最⼤堆内存
如果吞吐量⽬标达不到,则调⼤最⼤内存,不能让OS使⽤swap。如果还达不到,则降低⽬标。
吞吐量可以达到,GC暂停时间太长,则设置暂停时间的⽬标。
GC调优步骤静音冷却塔
打印GC⽇志:前⾯的博客《GC⽇志介绍》中已经介绍了GC⽇志的打印及分析
根据GC⽇志得到关键性能指标:将上⾯得到的GC⽇志通过GC⽇志可视化分析⼯具GCeasy和GCViewer,得到吞吐量、暂停时间、GC次数等关键指标,可以参考《GC⽇志可视化分析⼯具GCeasy和GCViewer》
分析GC原因,调整JVM参数:查看GC的次数和原因等,是young GC,还是Full GC,什么原因引起的young GC、Full GC。分析之后,根据选⽤的垃圾收集器调整相关的参数,重复上⾯步骤,观察调优结果。
Parallel收集器GC调优
ParallelGC调优准则
跟基本调优准则差不多
除⾮确定,否则不要设置最⼤堆内存
优先设置吞吐量⽬标
如果吞吐量⽬标达不到,则调⼤最⼤内存,不能让OS使⽤swap。如果还达不到,则降低⽬标。
吞吐量可以达到,GC暂停时间太长,则设置暂停时间的⽬标。
梁延淼ParallelGC调优案例
⽰例使⽤的是⼀个springboot程序打的jar包
第⼀步:因为不设置收集器的情况下,默认是⽤的就是Parallel垃圾收集器,所以这⾥只是设置了gc log的参数,启动命令如下:
nohup java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log  -jar demo.jar >/dev/null 2>&1&
启动完成后,将GC⽇志下载下来,⽤GCViewer打开如下:可以看到吞吐量为94.65%,young GC的
次数为16次(13次是因为young区内存分配失败,3次是因为Metaspace导致的)、full GC的次数为3次(是因为Metaspace导致的)、GC最⼩停顿时间为0.00314s、最⼤停顿时间0.21881s、平均停顿时间0.02571s。
第⼆步:通过上⾯可以看到Metaspace导致了6次gc,通过上⾯第⼆个截图看到Metaspace占⽤了55.4M,那我们通过参数-
XX:MetaspaceSize=64M 调⼤Metaspace的初始内存空间为64M,看下什么效果。启动命令如下:
nohup java -XX:MetaspaceSize=64M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log  -jar demo.jar >/dev/null 2>&1&
同上⾯⼀样将GC⽇志⽤GCViewer打开如下:可以看到吞吐量为97.72%,young GC的次数为14次(因为young区内存分配失败)、full GC的次数为0次、GC最⼩停顿时间为0.00251s、最⼤停顿时间0.0361s、平均停顿时间0.0361s。
可以明显看到调⼤了Metaspace后,吞吐量上升了,fullgc没有了,gc总次数减少了,gc停顿时间也变⼩了。
第三步:我们通过上图看到堆内存增长到了724M,那我们尝试将最⼤堆内存设置为1024M,观察⼀下有什么效果(调优基本原则不建议设置,除⾮明确知道所需内存⼤⼩),启动命令如下:
nohup java -Xmx1024M -XX:MetaspaceSize=64M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -
XX:+PrintGCDateStamps -Xloggc:./gc.log  -jar demo.jar >/dev/null 2>&1&
然后继续重复上⾯步骤,打开如下:可以看到吞吐量达到了99.75%,已经很⾼了;GC次数还是14次,但是有⼀次Metaspace导致的full GC,说明上⾯将其设置64M可能太⼩了,可以⾃⼰试下调⼤点看看效果;GC停顿时间要⽐第⼆步中变长了。
第四步,可以设置⼀个吞吐量(99%),gc停顿时间(100毫秒)的⽬标,启动命令如下:
0663.usnohup java -Xms1024M -Xmx1024M -XX:MetaspaceSize=64M  -XX:MaxGCPauseMillis=100 -XX:GCTimeRatio=99  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log -jar hgwd-usercenter.jar >/dev/null 2>&1&
可以看到如下结果:吞吐量⽐第三步下降了,但是由于我们设置了最⼤停顿时间100毫秒,我们看到GC停顿的最⼩、最⼤、平均停顿时间都⽐第三步减⼩了。

本文发布于:2024-09-23 14:26:26,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/102777.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:时间   垃圾   吞吐量   程序   内存
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议