9.9th仅为G1的百分之一。
也正是因为如此,ZGC简直是低延迟大内存服务的福音。话说如此,作者在尝试使用ZGC过程中还是发现一些问题:
-
因为整个ZGC周期基本都是并发执行,因此创建新对象的速度与垃圾回收的速度从一开始就在较量。如果创建新对象的速度更胜一筹,垃圾会将堆占满导致部分线程阻塞,直到垃圾回收完毕。
-
G1虽然是第一个基于全局的垃圾回收器,但是仍然存在新生代和老年代的概念。但是从ZGC开始,完全抛弃了新生代和老年代。但是新生代对象朝生夕灭的特性会给ZGC带来很大的压力。完全的并发执行,必然会造成一定的吞吐量降低。
-
在JDK11,G1垃圾回收器目前还只是实验性的功能,只支持Linux/x64平台。后续优化接改进,短时间内无法更新到JDK11中,所以可能会遇到一些不稳定因素。例如: 1. JDK12支持并发类卸载功能。2. JDK13将可回收内存从4TB支持到16TB。3. JDK14提升稳定性的同时,提高性能。4. JDK15从实验特性转变为可生产特性 。所以如果想要使用稳定的ZGC功能,只能升级到JDK17,横跨一个JDK11LTS版本,同时面临近200个JEP带来的功能更新。
-
实际线上生产环境,在订单商品等核心系统尝试使用ZGC。但是压测结果显示,在JDK11还是JDK17都差强人意。当然这并不是代表ZGC本身技术缺陷,而是需要根据不同的线上环境做更深度的调优和实践。因为数据保密等原因,这里没有给大家展示具体的压测数据,读者可以在各自环境进行不同程度的压测验证。
ZGC的原理介绍需要极大的篇幅,本文不打算对ZGC的底层技术展开大范围讨论。如果大家想要深入学习,作者推荐书籍《新一代垃圾回收器ZGC设计与实现》、Openjdk官网:ZGC介绍以及《深入理解Java虚拟机第五版》中的一些介绍。
2.2、G1垃圾回收器相关
总的来讲,得益于多个JEP优化,G1垃圾回收器无论是在JDK11还是JDK17都表现出了更强大的能力。随着CMS垃圾回收器的废弃,以及新生代ZGC的初出茅庐,G1垃圾回收器毫无疑问成了兼顾延迟和吞吐的最佳选择。通过多次压测结果观察,只是简单的提高JDK版本,就可以做到更低的GC时间、更短的GC间隔以及更少的CPU损耗。
场景 |
JDK |
并发 |
基线参考 |
TPS |
TPM |
TP99 |
TP999 |
TP9999 |
MAX CPU |
1.8.0_192 |
20 |
-Xms12g -Xmx12g -XX:+UseG1GC -XX:ParallelGCThreads=13 -XX:ConcGCThreads=4 |
1680 |
97640 |
10 |
28 |
31 |
32 |
50.07% |
11.0.8 |
20 |
-Xms12g -Xmx12g -XX:+UseG1GC -XX:ParallelGCThreads=13 -XX:ConcGCThreads=4 |
1714 |
99507 |
10 |
23 |
27 |
29 |
49.35% |
2.2.1、G1的Full GC从串行改为并行(JEP307)
? G1垃圾回收器,在 Mix GC回收垃圾的速度小于新对象分配的速度时,会发生Full GC。之前,发生Full GC时采用的是Serial Old算法,该算法使用单线程标记-清除-压缩算法,垃圾回收吞吐量较高,但是Stop-The-World时间变长。JDK10,为了减少G1垃圾回收器在发生Full GC时对应用造成的影响,Full GC采用并行标记-清除-压缩算法。该算法可以通过多线程协作 ,减少Stop-The-World时间。线程的数量可以由-XX:ParallelGCThreads选项来配置 ,但是这也会影响Young GC和Mixed GC线程数量。
2.2.2、可中断的Mixed-GC(JEP344)
G1垃圾回收器,通过一种名为CSet的数据结构辅助实现可预测停顿模型算法。CSet中存储了GC过程中可进行垃圾回收的Region集合。在本特性之前,CSet一旦被确定,就必须全部扫描并执行回收操作,这可能会导致超过预期的垃圾回收暂停时间。因此,JEP344针对这种问题进行了优化。Java12 中将把 Cset拆分为强制及可选两部分。有限执行强制部分的CSet,执行完成之后如果存在剩余时间,则继续处理可选Cset部分,从而让GC暂停时间更接近预期值。
2.2.3 G1支持NUMA技术(JEP345)
非统一内存访问架构(英语:non-uniform memory access,简称NUMA)是一种为多处理器的电脑设计的内存架构,内存访问时间取决于内存相对于处理器的位置。在NUMA下,处理器访问它自己的本地内存的速度比非本地内存(内存位于另一个处理器,或者是处理器之间共享的内存)快一些。ParallelGC在前几年已经开始支持NUMA技术,并且对于垃圾回收器性能有较大提升。可惜的是,G1垃圾回收器在JDK14之前一直不支持此项技术,现在可以通过参数+XX:+UseNUMA在使用G1垃圾回收器时使用NUMA技术。
2.3、废弃CMS垃圾回收器
CMS垃圾回收器在JDK9彻底被废弃,在JDK12直接被删除。目前,G1垃圾回收器是代替CMS的最优选择之一。
2.4、废弃ParallelScavenge + SerialOld 垃圾回收器组合
Java垃圾回收器有多种多样的组合和使用方式。下面这张图,我大概看过不差10遍,可是每次结果也是相同,记不住!!!!
默认垃圾回收器是哪些?
-XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseParallelGC -XX:+UseParNewGC 这几个参数有什么区别?
CMS垃圾回收器有哪些关键参数?浮动垃圾怎么处理?如何避免Full GC产生?
好消息!这些以后都不用记忆了,我们只需要专注攻克三款垃圾回收器原理:默认大哥G1、新晋新星ZGC、非亲儿子Shanondoah(了解)。这里也许有人会抬杠,小内存CMS会有更好的表现。ParNew仍然是高吞吐服务的首选。大道至简,简单易用才是王道。G1和ZGC必定是以后JVM垃圾回收器的重点发展方向,与其耗费精力记忆即将淘汰的技术,不如利出一孔,精通一门!
2.4、Epsilon:低开销垃圾回收器
Epsilon 垃圾回收器的目标是开发一个控制内存分配,但是不执行任何实际的垃圾回收工作。下面是该垃圾回收器的几个使用场景:性能测试、内存压力测试、极度短暂 job 任务、延迟改进、吞吐改进。
三、诊断和监控相关优化
3.1 Java Flight Recorder[JEP328]
Java Flight Recorder (JFR) 从正在运行的 Java 应用程序收集诊断和分析数据。 根据SPECjbb2015基准压测结果显示,JFR 对正在运行的 Java 应用程序的性能影响低于1%。 对于JFR的统计数据,可以使用 Java Mission Control (JMC) 和其他工具分析。 JFR 和 JMC 在 JDK 8 中是商业付费功能,而在 JDK11 中都是免费开源的。
3.2 Java Mission Control [JMS]
Java Mission Control (JMC) 可以分析并展示 Java Flight Recorder (JFR) 收集的数据,并且在 JDK 11 中是开源的。除了有关正在运行的应用程序的一般信息外,JMC 还允