写点什么

凭什么说 jdk11 比 jdk8 好?

作者:老地平线
  • 2021 年 12 月 02 日
  • 本文字数:3045 字

    阅读完需:约 10 分钟

凭什么说jdk11比jdk8好?

一、对比思路及结论

jdk8 与 jdk11 除了语法上的区别外,还有的是 gc 方面的优化,这是一个非常重要的方面。所以我们通过 jvm 的参数调整,来对比 jdk8 与 jdk11 在各 gc 算法上的区别。由于本人技术水平有限,在对比考量上可能存在不足之处,希望抛砖引玉,有兴趣的朋友一起研究。

结论先行:

1、jdk8-parallelGc 与 Jdk11-parallelGc 在同样条件下,jdk11 的表现略差,总停顿时间比 jdk8 增长 33.3%,平均 gc 时间增长 33.8%;

2、Jdk8-g1 与 Jdk11-g1 在同样条件下,相差无几;

3、在暂停时间上,ZGC 则不会超过 10ms,而 Parallel GC 和 G1GC 则高达 100ms+。jdk11-zgc 比 jdk11-g1,总停顿时间减少 62.8%,平均 gc 时间减少 10+倍;

二、准备工具

1、通过执行 jar 包的代码,生成 gc 的日志。

2、将 gc 的日志上传到 gc 分析的网站(https://gceasy.io/)得到 gc 的分析报告。

3、环境准备:

CentOS release 6.7 (Final)

Intel(R) Xeon(R) CPU E3-1226 v3 @ 3.30GHz

4c32G

三、测试代码

@Testpublic void gc1() {    ArrayList<Object> list = new ArrayList<>();    for (int i = 0; i < 500; i++) {        byte[] bytes = new byte[1024 * 100 * 5];        list.add(bytes);        System.out.println(i);        try {            Thread.sleep(100);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}
复制代码

此 maven 项目打包成 jar 包,放到 Linux 服务器上。

四、JVM 参数配置

基本配置参数:

-Xmx256M -Xms256M -XX:SurvivorRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaSpaceSize=512M -server

注:此处堆的大小有意设置为 256M 让其尽可能触发垃圾回收机制。


注:ZGC 在 jdk11 版本只能在 linux 上执行。jdk14 及后可以在 mac os 上执行。

参数说明:

1)-XX:+PrintGC 输出 GC 日志(这个只会显示总的 GC 堆的变化)。类似: -verbose:gc

(2)-XX:+PrintGCDetails 输出 GC 的详细日志(我最常用)

(3)-XX:+PrintGCTimeStamps 输出 GC 的时间戳(以基准时间的形式)

(4)-XX:+PrintGCDateStamp 输出 GC 的时间戳(以日期的形式,如:2020-08-13T22:17:35.354+0800

(6)-Xloggc:./logs/gc.log 日志文件的输出路径(jdk11 版本)

(7)-XX:+PrintCommandLineFlags 查看 JDK 不同版本使用的垃圾回收器

(8)-Xms600m -Xmx600m 初始化堆内存大小和最大堆内存大小

(9)-XX:MetaspaceSize=500m 指定元空间第一次触发垃圾回收的内存大小的阈值。当元空间内存占用不断增大,直到达到这个阈值时,就会触发一次垃圾回收。所以,适当的增大这个阈值,会减少垃圾回收的次数。默认值根据平台而定,一般情况下大约 20.8MB。

(10)-XX:MaxMetaspaceSize=500m 最大元空间大小

(11)-XX:SurvivorRatio 指定 Eden 区和一个 Survivor 区的空间大小的比率。默认为 8,即 Eden 区和一个 Survivor 区的空间大小为 8:1。

根据测试机配置所准备的对应执行脚本:

1、 /usr/local/jdk_server_1.8.0_77/bin/java -Xmx256M -Xms256M -XX:NewRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M -server -XX:+PrintGC -XX:+PrintGCDetails -Xloggc:./logs/gc-parallelGc-jdk-8.log -XX:+UseParallelGC -jar jdk-gc-research-1.0-SNAPSHOT.jar

2、 /usr/local/jdk_server_1.8.0_77/bin/java -Xmx256M -Xms256M -XX:NewRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M -server -XX:+PrintGC -XX:+PrintGCDetails -Xloggc:./logs/gc-g1-jdk-8.log -XX:+UseG1GC -jar jdk-gc-research-1.0-SNAPSHOT.jar

3、/usr/local/jdk-11.0.5/bin/java -Xmx256M -Xms256M -XX:NewRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M -server -Xlog:gc*=debug:file=./logs/gc-parallelGc-jdk11.log:utctime,level,tags:filecount=50,filesize=100M -XX:+UnlockExperimentalVMOptions -XX:+UseParallelGC -jar jdk-gc-research-1.0-SNAPSHOT.jar

4、/usr/local/jdk-11.0.5/bin/java -Xmx256M -Xms256M -XX:NewRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M -server -Xlog:gc*=debug:file=./logs/gc-g1-jdk11.log:utctime,level,tags:filecount=50,filesize=100M -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -jar jdk-gc-research-1.0-SNAPSHOT.jar

5、/usr/local/jdk-11.0.5/bin/java -Xmx256M -Xms256M -XX:NewRatio=4 -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=512M -server -Xlog:gc*=debug:file=./logs/gc-zgc-jdk11.log:utctime,level,tags:filecount=50,filesize=100M -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar jdk-gc-research-1.0-SNAPSHOT.jar

放到服务器上执行后,在 logs 目录下,就会生成以下文件:

gc-parallelGc-jdk-8.log

gc-g1-jdk-8.log

gc-parallelGc-jdk11.log

gc-g1-jdk11.log

gc-zgc-jdk11.log

导入 gc 分析网站得到结果并对比核心关键参数(网页报告,还有更多维度的比较,有兴趣的同学可以详细阅读)

效果图举例:



五、数据汇总


六、结论及想法

可得初步的结论:

1、jdk8-parallelGc 与 Jdk11-parallelGc 在同样条件下,jdk11 的表现略差,总停顿时间比 jdk8 增长 33.3%,平均 gc 时间增长 33.8%;

2、Jdk8-g1 与 Jdk11-g1 在同样条件下,相差无几;

3、在暂停时间上,ZGC 则不会超过 10ms,而 Parallel GC 和 G1GC 则高达 100ms+。jdk11-zgc 比 jdk11-g1,总停顿时间减少 62.8%,平均 gc 时间减少 10+倍;

其它想法:

1、由于 zgc 在 jdk11 中虽然只是试验性质的,但是在国外论坛上,不少程序员表示已经在生产环境基于 jdk11 上使用 zgc 多年,并未发现重大的问题(当项目升级至 jdk14 时,国外程序员是极推荐使用 zgc 算法)。但为保险起见,建议在测试环境尝试配置 zgc 作为运行测试,配合压力测试,以保证后期需要上生产的话,减少故障率。另外,不同的 GC 算法都有其长短处,ZGC 出现的最大优势是能够在保证停顿时间控制 10ms 以下,但为了实现这种高 SLA(业务延迟 SLA) 的停顿时间,其代价是性能的损失和内存消耗。有关文章表明,对于性能来说,不同的配置对性能的影响是不同的,如充足的内存下即大堆场景,ZGC 在各类 Benchmark 中能够超过 G1 大约 5% 到 20%,而在小堆情况下,则要低于 G1 大约 10%;

2、当前 ZGC 不支持压缩指针和分代 GC,其内存占用相对于 G1 来说要稍大,在小堆情况下较为明显,而在大堆情况下,这些多占用的内存则显得不那么突出。因此,以下两类应用强烈建议使用 ZGC 来提升业务体验:(1)超大堆应用。超大堆(百 G 以上)下,CMS 或者 G1 如果发生 Full GC,停顿会在分钟级别,可能会造成业务的终端,强烈推荐使用 ZGC。(2)高 SLA 需求的应用。如对响应时间有 P999 时限要求的实时和软实时应用,此类应用无论堆大小,均推荐采用低停顿的 ZGC。

3、退一步说,在某些项目上,我们持保守态度,不随便使用 zgc 的话(其实要看 g1 是否已经满足我们的线上服务的要求,如果通过监视 gc 的日志,分析 gc 并不频繁或者说未成为瓶颈,那尽量不要过渡优化)。因为在 jdk11 中,G1 已经取代了 CMS,是默认的垃圾收集器,假设已经项目升级到 jdk11,根据上面的测试结果,建议基于 G1 gc,对各个项目进行 jvm 的参数针对性的调优,本文不进行赘述。

4、本文介绍的是一种研究项目的 gc 情况的方法,希望对大家工作中有所帮助。


其它参考文章:

(深度剖析!全新的 ZGC 为我们解决什么问题!)https://blog.csdn.net/a1998321/article/details/108709585

(gc 图解过程) https://blog.csdn.net/weixin_42615068/article/details/102813947

(Tencent Kona JDK11 无暂停内存管理 ZGC 生产实践)https://new.qq.com/rain/a/20210614A02J4H00

发布于: 4 小时前阅读数: 6
用户头像

老地平线

关注

还未添加个人签名 2018.05.03 加入

还未添加个人简介

评论

发布
暂无评论
凭什么说jdk11比jdk8好?