GC 调优
GC 调优
GC 优化步骤
- 高可用,可用性达到几个
9 。 - 低延迟,请求必须多少毫秒内完成响应。
- 高吞吐,每秒完成多少次事务。
明确系统需求之所以重要,是因为上述性能指标间可能冲突。比如通常情况下,缩小延迟的代价是降低吞吐量或者消耗更多的内存或者两者同时发生。一般的业务场景会偏重于关注高可用与低延迟,如何量化
业务指标投射到

那么有
常见的调优策略
由于垃圾回收器种类繁多,针对不同的应用,调优策略也有所区别,因此下面介绍几种通用的的
-
选择合适的
GC 回收器。根据应用对延迟、吞吐的要求,结合各垃圾回收器的特点,合理选用。推荐使用G1 替换CMS 垃圾回收器,G1 的性能是在逐步优化的,在8GB 内存及以下的机器上,其各方面的表现也在赶上甚至有超越之势。G1 调参较方便,而CMS 垃圾回收器参数太过复杂、容易造成空间碎片化、对CPU 消耗较高等弊端,也使其目前处于废弃状态。Java 11 里新引入的ZGC 垃圾回收器,基本可用做到全阶段并发标记和回收,值得期待。 -
合理的堆内存大小设置。堆大小不要设置过大,建议不要超过系统内存的
75% ,避免出现系统内存耗尽。最大堆大小和初始化堆的大小保持一致,避免堆震荡。新生代的大小设置比较关键,我们调整GC 的频率和耗时,很多时候就是在调整新生代的大小,包括新生代和老年代的占比、新生代中Eden 区和Survivor 区的比例等,这些比例的设置还需要考虑各代中对象的晋升年龄,整个过程需要考虑的东西还是比较多的。如果使用G1 垃圾回收器,新生代大小这一块需要考虑的东西就少很多了,自适应的策略会决定每一次的回收集合(CSet) 。新生代的调整是GC 调优的核心,非常依赖经验,但是一般来说,Young GC 频率高,意味着新生代太小(或Eden 区和Survivor 配置不合理) ,Young GC 时间长,意味着新生代过大,这两个方向大体不差。 -
降低
Full GC 的频率。如果出现了频繁的Full GC 或者 老年代GC ,很有可能是存在内存泄漏,导致对象被长期持有,通过dump 内存快照进行分析,一般能较快地定位问题。除此之外,新生代和老年代的比例不合适,导致对象频频被直接分配到老年代,也有可能会造成Full GC ,这个时候需要结合业务代码和内存快照综合分析。 -
通过配置
GC 参数,可以帮助我们获取很多GC 调优所需的关键信息,如配置-XX:+PrintGCApplicationStoppedTime -XX:+PrintSafepointStatistics -XX:+PrintTenuringDistribution
,分别可以获取GC Pause 分布、安全点耗时统计、对象晋升年龄分布的信息,加上-XX:+PrintFlagsFinal 可以让我们了解最终生效的GC 参数等。