GC调优对咱们开发人员来讲,若是你想要技术方面一直发展下去,这部份内容的了解是必不可少的,jvm对于工做、面试来讲都很重要,GC调优的问题html
更是重中之重,由于是对你jvm学习内容的实践,知识只有应用实践出来才有意义,不然知识纸上谈兵。java
首先,咱们须要了解的内容,包括:面试
一、jvm内存结构:java虚拟(一)--java内存区域和常量池概念算法
二、垃圾收集算法:java虚拟机(五)--垃圾回收机制GC服务器
三、常见的垃圾收集器:java虚拟机(六)--垃圾收集器和内存分配策略oracle
四、GC日志分析:java虚拟机(十一)--GC日志分析 java虚拟机(十二)--可视化工具分析GC日志jvm
五、jvm常见参数:java虚拟机(九)--经常使用jvm参数ide
PS:本文GC调优非生产环境,只是我的Linux系统对一个简单项目的启动调优,经过GC日志调整相关参数,学习GC调优的方法,最终在生产环境获得应用工具
网上有不少生产环境GC调优的案例,请自行参考post
一、吞吐量
二、最大停顿时间
一、打印GC日志
二、根据日志得到关键性能指标
三、分析GC缘由,调优JVM参数
官网建议:
一、除非肯定,不然不要设置最大堆内存
二、优先设置吞吐量目标
三、若是吞吐量目标达不到,调大最大内存,不能让OS使用Swap,若是任然达不到,下降目标
四、若是吞吐量能达到,GC时间太长,设置停顿时间的目标
首先设置参数:
JAVA_OPTS="-XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/ -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log"
-XX:+DisableExplicitGC:是指禁止代码中经过system.gc()主动调用GC
将生成的GC日志经过GCeasy分析,首先看到吞吐量为93.78%
发生12GC,2次Full GC,10次Minor GC,Minor GC和Full GC的时间以下:
GC发生的缘由:
其中Ergonomics致使一次Full GC,耗时为130ms,时间最长
Metadata GC Threshold致使发生1次Full GC,一次Minor GC
Allocation Failure和GCLocker Initiated GC致使9次Minor GC
其中Ergonomics为jvm的自适应,根据CPU和内存状况自行调节jvm内存结构,可是也致使了一次Full GC
官方建议:除非很肯定,不然不要设置最大堆内存,因此这里不调节堆内存
一、由于Metaspace GC Thread出现Full GC,因此这里选择调节-XX:MetaspaceSize=64M,由于最大使用了22.74M
吞吐量有了提升,GC次数下降,最大GC Pause为70ms,因此咱们对于MetaspaceSize的调节是对的
二、对于一个测试项目来讲,咱们只是测试启动GC,95.94%的吞吐量,不够高,因此这里测试一下:
-XX:MaxGCPauseMillis=100 -XX:GCTimeRatio=99,最大GC时间位100ms,吞吐量为99%
发现为了提升吞吐量,吞吐量有了小幅度提高,可是GC时间却增加了不少
11次GC中有10次Minor GC,缘由都是Allocation Failure
三、咱们选择内存动态扩容增量参数,调节为30,咱们查询直到,默认为20%
# jinfo -flag YoungGenerationSizeIncrement 25436 -XX:YoungGenerationSizeIncrement=20
调节发现,吞吐量为94.346%,因此这里这个参数不太适合
因此GC调优就是不断试验的过程,调优的次数多了,就有了经验,还有其余不少参数,均可以试验测试,查看起到的做用
PS:我这里测试的参数可能和你的项目以及环境不一样,起到的做用可能不一样,例如动态扩容参数,换个项目可能就会有好的做用
官网建议:
一、年轻代大小:
避免使用-Xmn、-XX:NewRatio等显式设置Young区大小,会覆盖暂定时间目标
二、暂停时间目标:
暂停时间不要太苛刻,吞吐量目标为90%,太严苛影响吞吐量
三、关于Mixed GC调优参数:
-XX:InitiatingHeapOccupancyPercent:
堆占有率达到这个数值则触发global concurrent marking,默认45%
-XX:G1HeapWastePercent:
在global concurrent marking结束以后,能够知道区中有多少空间要被回收,在每次YGC以后和再次发生Mixed GC以前,会检查垃圾占比是
否达到这个参数,若是达到了,下次才会发生Mixed GC。
-XX:G1MixedGCLiveThresholdPercent:
Old区Region被回收的时候,存货对象的占比
-XX:G1MixedGCCountTarget:
-XX:G1OldSetRegionThresholdPercent:
一、默认状况下
When you see to-space overflow or to-space exhausted messages in your logs, the G1 GC does not have enough memory for either survivor or promoted objects, or for both. The Java heap cannot because it is already at its maximum. Example messages:
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]
To alleviate the problem, try the following adjustments:
Increase the value of the -XX:G1ReservePercent option (and the total heap accordingly) to increase the amount of reserve memory for "to-space".
Start the marking cycle earlier by reducing the value of -XX:InitiatingHeapOccupancyPercent.
Increase the value of the -XX:ConcGCThreads option to increase the number of parallel marking threads.
上面是官方建议:
对于Mixed GC,能够增长-XX:G1ReservePercent
选项的值(以及相应的总堆)以增长“to-space”的保留内存量
总共测试四次,以下表格:
最后修改的参数:-XX:GCTimeRatio=100,理论上对于G1垃圾收集器应该是很重要的,由于自己就是强调吞吐量,只是本次测试只是小的测试项目,
并且服务器配置比较渣,只有2个CPU,有些参数没法试验
总结:
咱们能够经过官方文档的建议,经过GC日志,结合解析工具,不管是GCeasy仍是GC View都是能够的,经过发生GC的缘由等问题逐渐调节参数,
官方文档必定要多看几遍,我只是简单浏览而已,后面确定会仔细看的。
GC调优指南:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/toc.html
如何选择垃圾收集器:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html
G1最佳实践:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#recommendations
G1 GC的一些关键技术:https://zhuanlan.zhihu.com/p/22591838