JVM GC 性能测试(三):真实流量

JVM GC 性能测试(三):真实流量

JVM GC 性能测试系列:


书接上文,在 JVM GC 性能测试(二):递增流量 的最后,D瓜哥提到了一个问题,对于在 JVM GC 性能测试(一):相同流量JVM GC 性能测试(二):递增流量 中存在的巨大 QPS 差异疑惑不解。所以,D瓜哥决定将测试机器接入到线上环境,在真实访问中,观察各个 GC 的表现。

一言以蔽之

  • J21-Gen-ZGC 和 J21-G1 无论在稳定性,吞吐量以及响应时效性上都非常优秀。

  • 再极端峰值情况,J21-G1 是更好的选择,更加稳定,不容易出凸点。

  • 日常使用,J21-Gen-ZGC 响应性更好,接口耗时更低。

鉴于 OpenJDK 21 G1 GC 一如既往的惊艳表现,D瓜哥准备整理一下 G1 GC 的主要优化,敬请关注: Java G1 垃圾收集器主要优化

1. 服务调用监控数据

监控服务调用的相关数据,这是对于用户来说,感知最强烈的相关数据,也是直接关系到服务质量的数据。

1.1. 服务调用次数

从调用次数上来看,五个分组没有大的变化,可以说根本没有达到系统的极限峰值。当然,这才是正常现象,如果日常运行都爆峰值,那说明系统早该扩容了。

服务调用次数(秒级)
图 1. 服务调用次数(秒级)
服务调用次数(分钟级)
图 2. 服务调用次数(分钟级)

1.2. 服务调用耗时

  • 整体上讲,J21-Gen-ZGC 的耗时更短,从数据上来看,TP999 能比 J21-G1 的少 10~20ms;TP99 更加夸张,J21-Gen-ZGC 的耗时只有 J21-G1 的一半。

  • J21-Gen-ZGC 和 J21-G1 还是一如既往的稳。

  • 这次测试中,J17-ZGC 也很稳,有些出乎意料。但是,结合下面 JVM CPU 使用率系统 CPU 使用率 来看,J17-ZGC 和 J21-ZGC 的 CPU 使用率早早就达到 90%+,再结合上面两个测试,从稳定性来看,J17-ZGC 和 J21-ZGC 只能被排除掉。

1.2.1. TP999

服务调用 TP999(分钟)
图 3. 服务调用 TP999(分钟)
服务调用 TP999(秒)
图 4. 服务调用 TP999(秒)

1.2.2. TP99

服务调用 TP99(分钟)
图 5. 服务调用 TP99(分钟)
服务调用 TP99(秒)
图 6. 服务调用 TP99(秒)

1.2.3. TP90

服务调用 TP90(分钟)
图 7. 服务调用 TP90(分钟)
服务调用 TP90(秒)
图 8. 服务调用 TP90(秒)

1.2.4. 最大耗时

服务调用耗时(秒级最大)
图 9. 服务调用耗时(秒级最大)
服务调用耗时(分钟级最大)
图 10. 服务调用耗时(分钟级最大)

1.3. 每台机器的调用次数及耗时

1.3.1. TP999 及调用次数

每台机器服务调用 TP999 及调用次数
图 11. 每台机器服务调用 TP999 及调用次数

1.3.2. TP99 及调用次数

每台机器服务调用 TP99 及调用次数
图 12. 每台机器服务调用 TP99 及调用次数

2. JVM 监控

2.1. CPU

单独从 CPU 使用率角度来看:

  • J21-ZGC 和 J17-ZGC 把 CPU 干到了 90%+,这还只是日常流量,如果有突发流量,就会非常危险。

  • J21-G1 一直非常稳定。

  • J21-Gen-ZGC 也很稳定,但是比 J21-G1 要高一些,大约高 10%~15%。

CPU 使用率(平均)
图 13. CPU 使用率(平均)
CPU 使用率(最大)
图 14. CPU 使用率(最大)
CPU 使用率(最小)
图 15. CPU 使用率(最小)

2.2. Young GC

关于 Young GC 的说明,D瓜哥在 JVM GC 性能测试(一):相同流量:Young GC 中,已经做了说明,这里就不再赘述。
  • 在日常流量场景下,J21-Gen-ZGC 的 Young GC 更低。

  • J8-G1 的 Young GC 有点高的出奇。

2.2.1. Young GC 次数

JVM Young GC 次数(平均)
图 16. JVM Young GC 次数(平均)
JVM Young GC 次数(最大)
图 17. JVM Young GC 次数(最大)
JVM Young GC 次数(最小)
图 18. JVM Young GC 次数(最小)

2.2.2. Young GC 耗时

JVM Young GC 耗时(平均)
图 19. JVM Young GC 耗时(平均)
JVM Young GC 耗时(最大)
图 20. JVM Young GC 耗时(最大)
JVM Young GC 耗时(最小)
图 21. JVM Young GC 耗时(最小)

2.3. Full GC

  • 整个过程,J21-G1 没有出现 Full GC,比上次 JVM GC 性能测试(二):递增流量 还要稳。

  • 只有 J21-Gen-ZGC 出现了 Full GC,5 台机器,每分钟不到一次,再结合 ZGC 不超过 0.5ms 的停顿,这个结果还是非常棒的。

2.3.1. Full GC 次数

JVM Full GC 次数(平均)
图 22. JVM Full GC 次数(平均)
JVM Full GC 次数(最大)
图 23. JVM Full GC 次数(最大)
JVM Full GC 次数(最小)
图 24. JVM Full GC 次数(最小)

2.3.2. Full GC 耗时

JVM Full GC 耗时(平均)
图 25. JVM Full GC 耗时(平均)
JVM Full GC 耗时(最大)
图 26. JVM Full GC 耗时(最大)
JVM Full GC 耗时(最小)
图 27. JVM Full GC 耗时(最小)

2.4. Heap

JVM 堆内存(平均)
图 28. JVM 堆内存(平均)
JVM 堆内存(最大)
图 29. JVM 堆内存(最大)
JVM 堆内存(最小)
图 30. JVM 堆内存(最小)

2.5. 非堆

JVM 非堆内存(平均)
图 31. JVM 非堆内存(平均)

2.6. 线程数

JVM 线程数(平均)
图 32. JVM 线程数(平均)
JVM 线程数(最大)
图 33. JVM 线程数(最大)
JVM 线程数(最小)
图 34. JVM 线程数(最小)

3. 系统监控

3.1. CPU 使用率

系统监控 CPU 使用率(分钟级平均)
图 35. 系统监控 CPU 使用率(分钟级平均)
系统监控 CPU 使用率(分钟级最大)
图 36. 系统监控 CPU 使用率(分钟级最大)
系统监控 CPU 使用率(分钟级最小)
图 37. 系统监控 CPU 使用率(分钟级最小)

3.2. 内存使用率

内存使用率(分钟级平均)
图 38. 内存使用率(分钟级平均)
内存使用率(分钟级最大)
图 39. 内存使用率(分钟级最大)
内存使用率(分钟级最小)
图 40. 内存使用率(分钟级最小)

3.3. 每个机器 CPU 使用率

每个机器 CPU 使用率
图 41. 每个机器 CPU 使用率

3.4. 每个机器系统负载

每个机器系统负载
图 42. 每个机器系统负载

下一步行动

在这次测试中,D瓜哥通过将正式环境的机器下线,让流量更多地转发到测试机器上。由此也带来了,部分接口响应慢,以及接口超过限流等告警,由于小伙伴的给力支持,在有惊无险中,顺利结束。所以,如果有研发同学也要做类似测试,一定要做好相关监控。

通过这三次测试来看,有充分的理由将 JVM 升级到 OpenJDK 21 了。Gen-ZGC + G1 可以完美替换 OpenJDK 8 的 G1 了。

在下一篇文章中,D瓜哥将分享自己将应用升级到 OpenJDK 21 中遇到的各种各样的问题,敬请关注: OpenJDK 21 升级指南