JVM性能提升50%,聊一聊背后的秘密武器Alibaba Dragonwell

简介: 你要知道的关于Alibaba Dragonwell一些重要优化措施。

9758F457-6F07-4076-AE86-9797DAE702DD.png

今年四月五日,阿里云开放了新一代ECS实例的邀测[1]Alibaba Dragonwell也在新ECS上进行了极致的优化。相比于之前的dragonwell_11.0.8.3版本,即将发布的dragonwell_11.0.11.6在SPECjbb2015[2] composite模式测试中,系统吞吐量max-jOPS提升55%,响应时间约束下的系统吞吐量critical-jOPS提升602%


如下图所示,图中数据做了归一化处理,以11.0.8.3_GA的critical-jOPS为1个基准单位。测试环境:阿里云80核,256g内存ECS实例,操作系统为Alinux3 [3]

C6C6751C-354B-4e55-9FB0-F7FB9C12A6A3.png

Alibaba Dragonwell


过去的十几年中,Java在阿里巴巴内部迅猛发展。阿里内使用Java语言编写的应用越来越多,数万的Java开发者每年产出超过十亿行Java代码这些代码都运行在阿里巴巴内部的OpenJDK定制版AJDK上。


Alibaba Dragonwell是AJDK的开源版[4](github链接见文章末尾),使用和OpenJDK一样的License,并永久免费。Alibaba Dragonwell有8和11两个版本,于2019年开源,当时仅支持x86-64架构,在2020年扩展到AArch64平台。


Alibaba Dragonwell结合阿里在线电商、金融、物流等各个业务场景做了大量细致优化,添加了协程/多租户/Jwarmup等诸多自研特性,并且在阿里云超大规模的服务器集群上经受了长时间大规模的验证。


调优方案与工具


由于SPECjbb2015动辄就需要两个小时才能得到一次完整的跑分分数,为了压榨性能调优单位时间内我们所能获得的信息量和性能试验的效率,我们开发了自动测试平台和性能分析工具来辅助SPECjbb2015性能调优,并且这套方法可以用在未来更多类似的性能调优案例中。


自动测试平台可以自动发起测试,并且在测试过程中调用基于perf的性能分析工具来采集CPU微架构数据以及系统热点数据,从而收集到每次实验过程中的关键性能数据,并将数据存档以可视化界面的形式展现,方便未来回顾和分析。


同时为了避免SPECjbb2015单次实验耗时长影响效率,跑性能实验时我们采用了SPECjbb2015特殊的PRESET模式该模式下可以指定压力指定时间来启动性能测试,不仅方便调优系统进行性能采集,还可以观察在一定压力下SPECjbb2015的系统热点和微架构数据情况。


我们通过该套调优系统获取到了Alibaba Dragonwell和其他JDK在跑SPECjbb2015时的热点和微架构数据,并且发现了诸多优化机会,如在GC热点和暂停时间上有较为明显的问题,从而深入到相关代码,并以性能数据为线索解决了相关的性能问题,具体的技术细节将在下文中向大家一一道来。


GC暂停时间优化


这项优化源于一个出人意料的发现,在SPECjbb2015中GC暂停时间竟然超过了总运行时间的20%,并且稳定复现。


通过上一小节中提到的调优系统,定位到出问题的是一个GC任务队列相关函数,并且明确的指向了原子Compare and Swap(CAS)相关代码。37DF97A2-94CA-4bf4-BAE5-C1414307AF7D.png

新ECS采用的CPU架构中CAS主要有如下的两种实现方式:

  • 使用带load-aquire和store-release语义的指令对的实现方式
  • LSE指令集中的CAS专项指令


多数JVM在GC中使用第一种方法,然而第二种在高冲突的情况下性能更加出色,因此Dragonwell改变了编译方式,使用LSE指令集实现CAS,有效的减少了暂停时间。下图展示了优化效果,我们采集了SPECjbb2015运行在不同核数上的GC数据,并采用吞吐量作为衡量GC性能的指标。    

     

吞吐量 = (运行时间 – Stop-The-World时间)/运行时间 * 100%

C7499CC0-7ACC-4508-9E4E-B17F6D428A84.png

我们可以看到优化前的CAS方式会造成吞吐量随使用的核数增加而剧烈下降,在80核的情况下甚至不足80%,而使用LSE CAS后吞吐量稳定在99%以上


对这个优化的另外两点补充说明:

1. 此改动只针对JVM内部的CAS实现,不包括JIT(Just-In-Time)生成的代码。JIT会动态检查硬件特性,在支持LSE指令集的系统上会优先使用LSE指令集。

2. 除了使用LSE CAS外,改变GC队列算法减少CAS也可以达到减少暂停时间的效果,OpenJDK社区在新版本中采用了这种方法。不过两种办法并不冲突,Alibaba Dragonwell同时采用了两种优化,达到了最优效果。


快速序列化


Alibaba Dragonwell在保证兼容性基础上对java原生序列化进行了优化通过缓存大幅提高了性能。通过分析发现, 原生序列化瓶颈大多在于大量的class 查找,如在反序列化时需要获取对端类定义的元信息等。引入了一层通过类全限定名和类加载器映射到java类对象的缓存,减少了大量Class.forName的调用。


具体做法:在反序列化时获取到类描述符,再根据类描述符查找信息时将会受限从classCache中查找,命中则立即返回,如果没有找到当前classloader和类全限定名唯一指定的类对象,将会走默认的类查找流程并且将结果缓存。同时, 在反序列化时会大量调用latestUserDefinedLoader 来查找首个用户定义的类加载器,因为此过程较重(涉及一次JNI调用和爬栈)也进行了缓存。


指令融合


指令融合是指将多个指令使用效率更高的一条或者几条指令进行替换从而提高性能。


Dragonwell对内存屏障/内存读写/比较跳转等多个场景做了优化,由于篇幅限制而且此类优化原理较为类似,在此仅举一例,三条指令融合成一条,如下图所示。

461850E5-2D36-4924-9C30-623E07D534CD.png

上面介绍了Alibaba Dragonwell内部的一些优化,下面我们换一个角度,从参数调优方面介绍对SPECjbb2015的优化。


大内存系统开启压缩指针


SPECjbb2015是一个内存敏感型的测试,压缩指针对SPECjbb2015分数的提升非常明显。不过默认情况下使用压缩指针最大只能用32g内存,这对80核的系统来说实在是太小了。其实通过适当的参数组合,我们完全可以在更大的内存中使用压缩指针。

CA4EB2CA-E8EF-46d0-A7C0-EF3F388508EA.png


首先我们了解下压缩指针的基本原理如上图所示,由于Java对象有明确的对齐要求,因此对象的地址必然由数个0结尾,0的个数由对齐位数决定。省略java对象地址结尾的数个0可解决内存而且不会丢失有效地址信息,需要访问对象时可以通过补0获得完整的地址。

由此可知,我们可以通过调整Java对象对齐位数控制压缩指针生效的最大内存。默认情况下Java为8字节对齐(3bit),加上压缩指针本身的的32bit,最多只能表示32g内存。但如果调整为32字节对齐,那么有37bit可以使用,也就是128g,这对于80核来说基本上够用了。


分层编译调优


分层编译是JVM最基础的机制之一,一般情况下对它改动比较少,不过在SPECjbb2015的场景下,在分层编译上仍有调优空间。首先介绍下分层编译。JVM在运行的时候动态的将字节码编译成机器码执行,JVM(hotspot)内部编译引擎主要有三个:

  1. 解释器:无编译开销,但解释执行效率很低。
  2. C1编译器:编译开销较低,生成代码质量一般。
  3. C2编译器:生成代码质量很高,但编译开销很高。


这三个编译引擎相互配合,执行次数较少的代码由解释器和C1负责,C2只编译热点代码,从而让Java可以达到峰值性能与编译开销的平衡,使应用运行更加平滑。


不过分层编译也有自己的缺点,一个较为明显的问题是它会增大生成代码的总量。下图展示SPECjbb2015运行时C1/C2编译方法数目。

5675C6A8-05C2-4ea6-9C5F-C489AEC406D5.png

图中Level1-3均为C1编译,根据收集运行信息的力度不同分为了三个等级,Level4为C2编译。我们可以看到C1编译了70%的方法,因此关闭分层编译,仅保留C2编译器可以减少生成代码,从而一定程度上提高高速缓存和叶表命中率。


对于SPECjbb2015来说,由于分数只取决于最后几分钟的峰值处理能力,前面大概两个小时的请求爬升阶段都可以视作预热,因此启动期的编译开销并不关键。我们可以关闭分层编译来减少生成代码,提高高速缓存和列表命中率。最终在测试中发现关闭分层编译生成代码总量由29M降低到9M,有明显减少。


本文总结了Alibaba Dragonwell的一些重要优化措施,请注意阿里承诺会持续的优化Dragonwell性能,同时更紧密地和OpenJDK等开源社区协作,贡献更多的定制化特性,促进Java技术的持续发展。


引用

[1] https://www.aliyun.com/daily-act/ecs/ecs_arm[2] SPECjbb2015是一款模拟电商应用的权威基准测试程序,包含了购买下单、折扣优惠、库存计算、客户数据存储与分析等典型电商应用行为:https://www.spec.org/jbb2015/[3]Alinux3:Alibaba Cloud Linux是阿里云推出的Linux发行版,它为云上应用程序环境提供Linux社区的最新增强功能,在提供云上最佳用户体验的同时,也针对阿里云基础设施做了深度的优化https://help.aliyun.com/document_detail/212631.html[4] Alibaba Dragonwell是阿里巴巴开源JDK:https://github.com/alibaba/dragonwell8https://github.com/alibaba/dragonwell11


(完)


加入龙蜥社群


加入微信群:添加社区助理-龙蜥社区小龙(微信:openanolis_assis),备注【龙蜥】拉你入群;加入钉钉群:可扫码或搜钉钉群号(33311793)。欢迎开发者/用户加入龙蜥OpenAnolis社区交流,共同推进龙蜥社区的发展,一起打造一个活跃的、健康的开源操作系统生态!

龙蜥助手.jpeg                1.jpeg

龙蜥社区_小龙                                            钉钉群二维码


关于龙蜥社区


龙蜥社区是由企事业单位、高等院校、科研单位、非营利性组织、个人等按照自愿、平等、开源、协作的基础上组成的非盈利性开源社区。龙蜥社区成立于2020年9月,旨在构建一个开源、中立、开放的Linux上游发行版社区及创新平台。


短期目标是开发Anolis OS作为CentOS替代版,重新构建一个兼容国际Linux主流厂商发行版。中长期目标是探索打造一个面向未来的操作系统,建立统一的开源操作系统生态,孵化创新开源项目,繁荣开源生态。


加入我们,一起打造面向未来的开源操作系统!

Https://openanolis.cn

相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
存储 监控 算法
jvm-性能调优(二)
jvm-性能调优(二)
|
6月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
568 3
|
6月前
|
监控 Java 测试技术
JVM 性能调优 及 为什么要减少 Full GC
JVM 性能调优 及 为什么要减少 Full GC
139 4
|
7月前
|
监控 Java 调度
探秘Java虚拟机(JVM)性能调优:技术要点与实战策略
【6月更文挑战第30天】**探索JVM性能调优:**关注堆内存配置(Xms, Xmx, XX:NewRatio, XX:SurvivorRatio),选择适合的垃圾收集器(如Parallel, CMS, G1),利用jstat, jmap等工具诊断,解决Full GC问题,实战中结合MAT分析内存泄露。调优是平衡内存占用、延迟和吞吐量的艺术,借助VisualVM等工具提升系统在高负载下的稳定性与效率。
113 1
|
3月前
|
存储 缓存 监控
聊聊JIT是如何影响JVM性能的!
聊聊JIT是如何影响JVM性能的!
|
4月前
|
Kubernetes Java 编译器
解锁极致性能:Quarkus如何让JVM应用调优变得前所未有的简单与高效!
Quarkus是一款专为GraalVM和OpenJDK设计的Kubernetes Native Java框架,采用AOT编译技术将Java应用转化为本地代码,大幅提升启动速度与运行效率。它简化了性能调优流程,如自动优化垃圾回收、类加载、内存管理及线程管理等,使开发者无需深入理解JVM细节即可轻松提升应用性能。与传统JVM应用相比,Quarkus显著降低了性能调优的复杂度。
144 2
|
6月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
134 8
|
6月前
|
缓存 监控 Java
Java虚拟机(JVM)性能调优实战指南
在追求软件开发卓越的征途中,Java虚拟机(JVM)性能调优是一个不可或缺的环节。本文将通过具体的数据和案例,深入探讨JVM性能调优的理论基础与实践技巧,旨在为广大Java开发者提供一套系统化的性能优化方案。文章首先剖析了JVM内存管理机制的工作原理,然后通过对比分析不同垃圾收集器的适用场景及性能表现,为读者揭示了选择合适垃圾回收策略的数据支持。接下来,结合线程管理和JIT编译优化等高级话题,文章详细阐述了如何利用现代JVM提供的丰富工具进行问题诊断和性能监控。最后,通过实际案例分析,展示了性能调优过程中可能遇到的挑战及应对策略,确保读者能够将理论运用于实践,有效提升Java应用的性能。 【
224 10
|
6月前
|
JSON Java BI
一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优。如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误。本次调优的代码是埋点系统中的报表分析功能,小公司,开发结束后,没有Code Review环节,所以下面某些问题,也许在Code Review环节就可以避免。
172 0
一次Java性能调优实践【代码+JVM 性能提升70%】
|
6月前
|
缓存 监控 算法
Java面试题:讨论JVM性能调优的常见方法和技巧。
Java面试题:讨论JVM性能调优的常见方法和技巧。
66 1

热门文章

最新文章

下一篇
开通oss服务