从8到17,java有哪些进步
JDK17发布已有数月时间,它不仅包括了许多新的语言特性,而且与老版本的JDK相比,性能的提升也很明显。JDK17比以前的LTS版本JDK8和JDK11对性能的提高尤其显著。
从8到17,java有哪些进步
为不同的目的服务。
有时候,用哪个垃圾回收器并不是一目了然。理解这一点很重要,因为你必须先弄清楚你的主要目标是什么。常用目标包括优化吞吐量、延迟和/或资源占用情况。当然,最好的解决方法就是对上面的所有目标进行优化,并且在每一种情况下都达到最优。收集器力图从各个方面进行优化,但是必须针对不同的目标进行不同的折衷。
以下是一个不同优化的简单说明:
吞吐:减少GC对在指定时间内可以完成的事务总数的影响。
延时:减少GC对一个交易的影响。
资源消耗:减少GC使用额外资源。
这种差异并不意味着收集器不能全面优化。对收集器进行优化时,大部分工作都是确保尽可能高效的权衡。也有一个全面改善的好办法,就是重新评估旧的设计决定,然后提出一个更好的解决方案。
从JDK8开始就进步了。
从JDK8开始,我们就可以看到所有收集器在各方面都有了或多或少的改善。为显示GC的进展,以下比较将使用标准化分数来比较单个收集器。作为对比,我使用SPECjbb®20151,堆大小设置为16GB。这个测试是一种广为人知和非常稳定的基准,并且不仅仅关注于GC的性能,所以结果能够显示Java平台整体上的进步。该基准具有多个不同的模式,它们能够同时产生吞吐量指标和延迟度量。延时度量度量在响应时间限制下的吞吐量。
为了进行停顿时间比较,我在固定负载下运行了一个小时的基准。也就是,所有收集器都承担同样程度的负荷。
最终要注意,ZGC是JDK11(从JDK15正式投入使用),所以我们只有两个ZGC数据点,而G1和Parallel则有三个数据点。
吞吐量
所有的收集器都比老版本有了很大的提高,其中ZGC的提升最大。G1和Parallel在测试中有更好的原始吞吐量,但是增加了堆空间之后,ZGC就弥补了这个缺口。
在讨论这一指标时,我们应该注意,我们不仅是衡量GC的性能。Java平台的其他部分,比如JIT编译器,也会提供一些帮助。
延迟
延时提升效果更加显著。减少GC停顿时间的努力都是值得的。说到这一点,我们应该理解,事实上,许多提升都是由于GC的改善。
对这一指标,G1是进步最大的。ZGC在延迟方面也取得了重大进步。因为基准度量了应用程序的延迟。ZGC可以最大限度地减少停顿时间,并且我们发现其他因素对测试结果也有影响。若对停顿时间的改进进行研究,将会发现ZGC起到重要作用。
在JDK17中可以看到ZGC远远低于目标:次毫秒级暂停。G1旨在平衡延时和吞吐量,这比默认的目标要低得多:200毫秒的停顿时间。ZGC的设计保证停顿时间不会随着堆的大小而变化,当堆扩展到128GB时,这是一种清晰的现象。就停顿时间而言,G1比Parallel能更好地处理较大堆,因为它可以保证停顿时间符合特定的目标。
资源占用
Parallel和ZGC非常稳定,所以我们可以看看原始的数据。很明显,G1在这方面有了很大的改善,主要是因为所有的特性和增强都提高了记忆集管理的效率。
尽管其它收集器的开销并未减少,但是我们还是应该记住,它们也在其他方面得到了改进,所以不需要额外的内存。
升级
不管使用什么收集器,JDK17的总体性能比老版本有了很大的提高。如果您还在使用JDK8,并且计划进行升级,现在您可以重新评估打算使用的GC。Parallel是JDK8的缺省值,但在JDK9中则为G1。自那时起,G1比Parallel更快,但是Parallel在某些情况下还是最好的选择。随着ZGC(从JDK15开始正式使用)的加入,成为第三个高性能替代品。