四、优化方案/验证方案
上面已分析出当前配置存在的较为明显的不足,下面优化方案主要先针对性解决这些问题,之后再结合效果决定是否继续深入优化。
当前主流/优秀的搜集器包含:
- Parrallel Scavenge + Parrallel Old:吞吐量优先,后台任务型服务适合;
- ParNew + CMS:经典的低停顿搜集器,绝大多数商用、延时敏感的服务在使用;
- G1:JDK 9默认搜集器,堆内存比较大(6G-8G以上)的时候表现出比较高吞吐量和短暂的停顿时间;
- ZGC:JDK 11中推出的一款低延迟垃圾回收器,目前处在实验阶段;
结合当前服务的实际情况(堆大小,可维护性),我们选择ParNew + CMS方案是比较合适的。
参数选择的原则如下:
1)Meta区域的大小一定要指定,且MetaspaceSize和MaxMetaspaceSize大小应设置一致,具体多大要结合线上实例的情况,通过jstat -gc可以获取该服务线上实例的情况。
# jstat -gc 31247 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 37888.0 37888.0 0.0 32438.5 972800.0 403063.5 3145728.0 2700882.3 167320.0 152285.0 18856.0 16442.4 15189 597.209 65 70.447 667.655
可以看出MU在150M左右,
因此-XX:MetaspaceSize=256M
-XX:MaxMetaspaceSize=256M是比较合理的。
2)Young区也不是越大越好。
当堆大小一定时,Young区越大,Young GC的频率一定越小,但Old区域就会变小,如果太小,稍微晋升一些对象就会触发Full GC得不偿失。
如果Young区过小,Young GC就会比较频繁,这样Old区就会比较大,单次Full GC的停顿就会比较大。因此Young区的大小需要结合服务情况,分几种场景进行比较,最终获得最合适的配置。
基于以上原则,以下为4种参数组合:
1.ParNew +CMS,Young区扩大1倍
-Xms4096M -Xmx4096M -Xmn2048M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSScavengeBeforeRemark
2.ParNew +CMS,Young区扩大1倍,
去除-XX:+CMSScavengeBeforeRemark
(使用【-XX:CMSScavengeBeforeRemark】参数可以做到在重新标记前先执行一次新生代GC)。
因为老年代和年轻代之间的对象存在跨代引用,因此老年代进行GC Roots追踪时,同样也会扫描年轻代,而如果能够在重新标记前先执行一次新生代GC,那么就可以少扫描一些对象,重新标记阶段的性能也能因此提升。)
-Xms4096M -Xmx4096M -Xmn2048M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
3.ParNew +CMS,Young区扩大0.5倍
-Xms4096M -Xmx4096M -Xmn1536M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSScavengeBeforeRemark
4.ParNew +CMS,Young区不变
下面,我们需要在压测环境,对不同负载下4种方案的实际表现进行比较,分析,验证。
4.1 压测环境验证/分析
高负载场景(1100 QPS)GC表现
可以看出,在高负载场景,4种ParNew + CMS的各项指标表现均远好于Parrallel Scavenge + Parrallel Old。其中:
- 方案4(Young区扩大0.5倍)表现最佳,接口P95,P99延时相对当前方案降低50%,Full GC累积耗时减少88%, Young GC次数减少23%,Young GC累积耗时减少4%,Young区调大后,虽然次数减少了,但Young区大了,单次Young GC的耗时也大概率会上升,这是符合预期的。
- Young区扩大1倍的两种方案,即方案2和方案3,表现接近,接口P95,P99延时相对当前方案降低40%,Full GC累积耗时减少81%, Young GC次数减少43%,Young GC累积耗时减少17%,略逊于Young区扩大0.5倍,总体表现不错,这两个方案进行合并,不再区分。
Young区不变的方案在新方案里,表现最差,淘汰。所以在中负载场景,我们只需要对比方案2和方案4。
中负载场景(600 QPS)GC表现
可以看出,在中负载场景,2种ParNew + CMS(方案2和方案4)的各项指标表现也均远好于Parrallel Scavenge + Parrallel Old。
- Young区扩大1倍的方案表现最佳,接口P95,P99延时相对当前方案降低32%,Full GC累积耗时减少93%, Young GC次数减少42%,Young GC累积耗时减少44%;
- Young区扩大0.5倍的方案稍逊一些。
综合来看,两个方案表现十分接近,原则上两种方案都可以,只是Young区扩大0.5倍的方案在业务高峰期的表现更佳,为尽量保证高峰期服务的稳定和性能,目前更倾向于选择ParNew + CMS,Young区扩大0.5倍方案。