JVM性能提升50%,聊一聊背后的秘密武器Alibaba Dragonwell
简介: 你要知道的关于Alibaba Dragonwell一些重要优化措施。
今年四月五日,阿里云开放了新一代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]。
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)相关代码。
新ECS采用的CPU架构中CAS主要有如下的两种实现方式:
- 使用带load-aquire和store-release语义的指令对的实现方式
- LSE指令集中的CAS专项指令
多数JVM在GC中使用第一种方法,然而第二种在高冲突的情况下性能更加出色,因此Dragonwell改变了编译方式,使用LSE指令集实现CAS,有效的减少了暂停时间。下图展示了优化效果,我们采集了SPECjbb2015运行在不同核数上的GC数据,并采用吞吐量作为衡量GC性能的指标。
吞吐量 = (运行时间 – Stop-The-World时间)/运行时间 * 100%
我们可以看到优化前的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对内存屏障/内存读写/比较跳转等多个场景做了优化,由于篇幅限制而且此类优化原理较为类似,在此仅举一例,三条指令融合成一条,如下图所示。
上面介绍了Alibaba Dragonwell内部的一些优化,下面我们换一个角度,从参数调优方面介绍对SPECjbb2015的优化。
大内存系统开启压缩指针
SPECjbb2015是一个内存敏感型的测试,压缩指针对SPECjbb2015分数的提升非常明显。不过默认情况下使用压缩指针最大只能用32g内存,这对80核的系统来说实在是太小了。其实通过适当的参数组合,我们完全可以在更大的内存中使用压缩指针。
首先我们了解下压缩指针的基本原理。如上图所示,由于Java对象有明确的对齐要求,因此对象的地址必然由数个0结尾,0的个数由对齐位数决定。省略java对象地址结尾的数个0可解决内存而且不会丢失有效地址信息,需要访问对象时可以通过补0获得完整的地址。
由此可知,我们可以通过调整Java对象对齐位数控制压缩指针生效的最大内存。默认情况下Java为8字节对齐(3bit),加上压缩指针本身的的32bit,最多只能表示32g内存。但如果调整为32字节对齐,那么有37bit可以使用,也就是128g,这对于80核来说基本上够用了。
分层编译调优
分层编译是JVM最基础的机制之一,一般情况下对它改动比较少,不过在SPECjbb2015的场景下,在分层编译上仍有调优空间。首先介绍下分层编译。JVM在运行的时候动态的将字节码编译成机器码执行,JVM(hotspot)内部编译引擎主要有三个:
- 解释器:无编译开销,但解释执行效率很低。
- C1编译器:编译开销较低,生成代码质量一般。
- C2编译器:生成代码质量很高,但编译开销很高。
这三个编译引擎相互配合,执行次数较少的代码由解释器和C1负责,C2只编译热点代码,从而让Java可以达到峰值性能与编译开销的平衡,使应用运行更加平滑。
不过分层编译也有自己的缺点,一个较为明显的问题是它会增大生成代码的总量。下图展示SPECjbb2015运行时C1/C2编译方法数目。
图中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
原文链接
本文为阿里云原创内容,未经允许不得转载。
JVM性能提升50%,聊一聊背后的秘密武器Alibaba Dragonwell的更多相关文章
- 天天动听MP3解码器性能提升50%
天天动听今日升级提醒,发现有一句 “使用新的MP3解码器,性能提升50%”,太惊讶了. 之前版本的MP3解码器使用libmpg123,效果已经是MP3解码器中非常不错的了. 50%的提升,应该不仅仅是 ...
- php 性能优化之opcache - 让你的php性能提升 50%
性能提升原理:减少文件解析的时间. 我们都知道,程序要运行,得有一个编译或者解析的过程,编译或解析之后的代码才是机器可以运行的. 而 php 是一种解析性语言,在使用php来处理http请求的时候,每 ...
- 再谈HTTP2性能提升之背后原理—HTTP2历史解剖
即使千辛万苦,还是把网站升级到http2了,遇坑如<phpcms v9站http升级到https加http2遇到到坑>. 因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1 ...
- JVM 性能调优实战之:一次系统性能瓶颈的寻找过程
玩过性能优化的朋友都清楚,性能优化的关键并不在于怎么进行优化,而在于怎么找到当前系统的性能瓶颈.性能优化分为好几个层次,比如系统层次.算法层次.代码层次…JVM 的性能优化被认为是底层优化,门槛较高, ...
- JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码
本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...
- 增强学习 | AlphaGo背后的秘密
"敢于尝试,才有突破" 2017年5月27日,当今世界排名第一的中国棋手柯洁与AlphaGo 2.0的三局对战落败.该事件标志着最新的人工智能技术在围棋竞技领域超越了人类智能,借此 ...
- JVM性能调优入门
1. 背景 虽然大多数应用程序使用JVM的默认设置就能很好地工作,仍然有不少应用程序需要对JVM进行额外的配置才能达到其期望的性能要求. 现在JVM为了满足各种应用的需要,为程序运行提供了大量的JVM ...
- 使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码 (jvm性能调优)
技术交流群:233513714 本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 ...
- JVM性能优化, Part 3 垃圾回收
ImportNew注:本文是JVM性能优化 系列-第3篇-<JVM性能优化, Part 3 —— 垃圾回收> 第一篇 <JVM性能优化, Part 1 ―― JVM简介 > 第 ...
- JVM性能优化, Part 2 ―― 编译器
作为JVM性能优化系列文章的第2篇,本文将着重介绍Java编译器,此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化,Part 1″中对JVM的介绍).Eva Andreasson ...
随机推荐
- 【Django】HTML如何显示富文本内容
一.背景 我采用的前端样式是 LayUI,通过它的富文本编辑器保存内容到数据库后,遇到了一个回显到页面的问题 二.方案 在不考虑使用 Vue 的情况下,有一种简单的方式 <div id=&quo ...
- Android 开发Day8
/* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * gradle pl ...
- NJUPT自控第一次积分赛的小总结(二)基于simpleFOC的无刷电机控制
新人一枚,写的比较水,欢迎大佬指正! 先说一下我用的物料与开发环境吧: 无刷电机:makerbase的2804电机(带AS5600磁编码器) 电机驱动板:simpleFOCmini(学校推荐的) 电池 ...
- 引领文旅新体验!3DCAT实时云渲染助力打造“永不落幕”的湾区文采会元宇宙
2022年11月25日至27日,2022年粤港澳大湾区公共文化和旅游产品(东莞)采购会(简称"湾区文采会")在广东省东莞市文化馆举行. 文采会期间,文采会元宇宙线上虚拟展厅全新亮相 ...
- 智慧党建3D可视化方案,扩大党建文化宣传数字网络影响力
信息技术的快速发展加快了社会分化解构,重构了人际传播渠道.随着党员中网民."数字原住民"比重持续攀升,党员工作生活信息化.网络化.数据化持续加深,传统的党建方式对党员,特别是年轻一 ...
- 误删除系统超级用户(superuser)权限的恢复方式
在使用KingbaseES数据库的时候,系统默认存在一个跟系统初始化用户同名的Superuser(默认是system用户,可更改). 这个Superuser的存在其实对于权限的管控是很有用的,但是如果 ...
- Vue入门笔记二
<Vue.js项目实战> 开发所需的包称为开发依赖,应该使用--save-dev标志进行安装 应用运行需要的直接依赖应该使用--save标志进行安装 模板 使用Pug Pug(以前称为Ja ...
- #树上带修莫队,树链剖分#洛谷 4074 [WC2013]糖果公园
题目 分析 考虑将树转换成序列求解,那就用欧拉序,入栈一次出栈一次正好抵消掉 注意当起点不是LCA的时候要将起点加入,剩下就是带修莫队板子题了 代码 #include <cstdio> # ...
- 一文读懂java中的Reference和引用类型
目录 简介 强引用Strong Reference 软引用Soft Reference 弱引用weak Reference 虚引用PhantomReference Reference和Referenc ...
- 熊磊:成功移植 OpenHarmony 到多套开发板,是最开心的事
编者按:在 OpenHarmony 生态发展过程中,涌现了大批优秀的代码贡献者,本专题旨在表彰贡献.分享经验,文中内容来自嘉宾访谈,不代表 OpenHarmony 工作委员会观点. 熊磊 华为技术有限 ...