2021 年 6 月 30 日,毕昇 JDK update Q2 版本正式发布,下载方式见文末参考链接。该版本在同步 OpenJDK 社区 8u292/11.0.11 的基础上,还包含如下更新,为用户提供高性能、可用于生产环境的 OpenJDK 发行版。
-
提供鲲鹏硬件加速的 KAEProvider 支持 DH,RSA 签名等众多算法(毕昇 JDK8)
-
Jmap 并行扫描优化支持 CMS(毕昇 JDK8, 毕昇 JDK11)
-
G1 GC 实现 numa-aware 特性(毕昇 JDK8)
-
G1 GC numa-aware 优化(毕昇 JDK11)
-
Bug fixes
鲲鹏硬件加速的 KAEProvider(毕昇 JDK8)
KAE(Kunpeng Accelerate Engine)加解密是鲲鹏 920 处理器提供的硬件加速方案,可以显著降低处理器消耗,提高处理器效率. 毕昇 JDK 8u282 为 Java 用户提供 了 KAEProvider,使 Java 开发人员可以直接使用硬件带来的加速效果,但支持算法有限。此版本在 282 的基础上,新增 DH、ECDH、RSA 签名、AES-GCM 等算法,有效提升应用在 HTTPS 中的处理性能。同时提供对国密算法 SM3 和 SM4 的支持,其中 SM4 支持 ECB/CBC/CTR/OFB 模式。
到目前为止,毕昇 JDK 除了默认 Provider 不支持的加密模式外(例如 AES/XTS 模式),已支持 KAE 硬件加速引擎中的所有加解密算法,KAEProvider 具体实现的算法如下:
算法 | 说明 |
摘要算法 | 包括MD5、SHA256、SHA384、SM3 |
对称加密算法AES | 支持ECB、CBC、CTR、GCM模式 |
对称加密算法SM4 | 包括ECB、CBC、CTR、OFB模式 |
HMac | 包括HmacMD5、HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA51 |
非对称加解密算法RSA | 支持512、1024、2048、3072、4096位秘钥大小 |
DH | 包括DHKeyPairGenerator和DHKeyAgreement,支持512、1024、2048、3072、4096位秘钥 |
ECDH | 包括ECKeyPairGenerator和ECDHKeyAgreement,支持曲线secp224r1、prime256v1、secp384r1、secp521r1 |
RSA签名 | 包括RSASignature和RSAPSSSignature,私钥只支持RSAPrivateCrtKey |
实现
KAEProvider 的实现原理在前期已有介绍,详见openEuler 21.03 特性解读 | 毕昇 JDK8 支持鲲鹏硬件加解密特性详解和使用介绍. 简而言之, KAEProvider 通过实现 JDK 中的特定的 SPI(Service Provider Interface)接口支持具体的算法,此版本实现的 SPI 类如下:
Spi类 | 实现类 | 说明 |
MessageDigestSpi | KAEDigest | 支持SM3算法 |
KeyAgreementSpi | KAEDHKeyAgreement | 支持512、1024、2048、3072、4096位的秘钥 |
KAEECDHKeyAgreement | 支持曲线secp224r1、prime256v1、secp384r1、secp521r1 | |
KeyPairGeneratorSpi | KAEDHKeyPairGenerator | 当前支持生成512、1024、2048、3072、4096位的秘钥 |
KAEECKeyPairGenerator | 支持生成224、256、384、521位的秘钥 | |
CipherSpi | KAEAESCipher | 支持GCM模式 |
KAESM4Cipher | 支持ECB、CBC、CTR、OFB模式 | |
SignatureSpi | KAERSASignature | 支持“SHA1withRSA”, “SHA224withRSA”, “SHA384withRSA”, “SHA256withRSA”, “SHA512withRSA“, 私钥只支持RSAPrivateCrtKey |
KAERSAPSSSignature | 支持SHA-1“, ”SHA-224“, ”SHA-256“, ”SHA-384“, ”SHA-512“, 私钥只支持RSAPrivateCrtKey |
除此之外,毕昇 JDK 为用户提供$JAVA_HOME/lib/ext/kaeprovider.conf 文件,方便用户启动或关闭 KAEProvider 中的某些算法,默认启用所有算法,文件内容如下:
#
# This is the config file for KAEProvider
#
# Algorithms are enabled by default if KAEProvider is used.
# Delete # if you want to disable certain algorithm.
# kae.md5=false
# kae.sha256=false
# kae.sha384=false
# kae.sm3=false
# kae.aes=false
# kae.sm4=false
# kae.hmac=false
# kae.rsa=false
# kae.dh=false
# kae.ec=false
# enable KAEProvider log setting
# kae.log=true
用户也可通过打开此文件的日志选项,来查看是否检测到了机器上的 kae 引擎。如果打开了此选项,并在用户的机器上检测到了 kae 引擎,则会将日志写入进程启动目录下的 kae.log 文件,如下所示:
性能测试
测试环境:
-
CPU: Kunpeng 920
-
OS: openEuler 20.03
-
KAE: v1.3.10
-
JDK: 毕昇 JDK 1.8.0_292
JMH
测试用例请参加毕昇 JDK 代码仓[3].
如下为 DH 的测试结果,可以看到与 JDK 默认的 Provider 相比,当秘钥长度为 2048 时,平均性能提升 360%;当秘钥长度为 4096 时,平均性能提升 460%:
如下为 RSAPSS 签名的测试结果,可以看到与 JDK 默认的 Provider 签名 1k 的数据相比,当秘钥长度为 2048 时,平均性能提升 390%,当秘钥长度为 4096 时,平均性能提升 485%.
HTTPS
-
服务端 Tomcat: 9.0.46
-
客户端 Jmeter: 5.4.1
-
步骤:
-
Tomcat: 默认 Provider/KAEProvider
-
Jmeter: 默认 Provider
默认 Provider 的结果如下:
KAEProvider 的结果如下:
结论:与 JDK 默认的 Provider 相比,在 HTTPS 短连接场景下,KAEProvider 可以提升 93%.
Jmap 并行扫描优化支持 CMS(毕昇 JDK8, 毕昇 JDK11)
背景
当前 jmap 采用单线程对 java 堆进行扫描,扫描速度较慢,并且对超大堆进行扫描时(大于 200G),容易引起系统卡死。因此可以通过多线程来进行扫描,减少卡顿时间。之前发布的版本支持了 G1GC 与 ParallelGC 并行扫描,本次发布增加对 CMS GC 的支持。
实现
毕昇 JDK 在社区高版本 jmap 优化回合的基础上,在 cms heap 上部署 CMSHeapBlockClaimer 用来为每个线程分配 heap block,增加了 object_iterate_block 接口用来扫描 block 中的 object,每个线程的扫描结果会在已有的 heap_inspection 模块中的 ParHeapInspectTask 进行合并。具体包含内容如下:
-
整体扫描策略: 可用的GC线程(active_workers)有两个用来扫描年轻代,一个扫描suvivor区,另一个扫描eden区;剩下的线程全部用来扫描老年代。
-
GC线程任务划分:在CMSHeap模块中新增CMSHeapBlockClaimer类,提供claim_and_get_block接口用来为每一个线程生成唯一的block_index, GC线程根据block_index来确定自己要扫描的区域。
-
年轻代扫描策略:年轻代的eden(block_index = 0)跟survivor(block_index = 1)区会被分别当做一个整体的block,GC线程扫描时沿用现有的扫描接口object_iterate。
-
老年代扫描策略:+ 老年代被分成一个个 1M 大小的 block,block 大小由参数 IterateBlockSize 决定。+ 在 ConcurrentMarkSweepGeneration 中新增 object_iterate_block 方法来扫描 block。
用户可通过在 jmap -histo 后增加 parallel 参数来使用此特性,如下所示:
-
jmap -histo:live,parallel=3 pid : 指定并行线程数为 3
-
jmap -histo:live,parallel=0 pid : 使用当前系统可支持的并行线程数(-XX:ParallelGCThreads)
-
jmap -histo:live,parallel=1 pid : 使用原有的串行扫描
性能测试
测试环境:
-
CPU: Kunpeng 920
-
OS: openEuler 20.03
-
JDK: 毕昇 JDK1.8.0_292、毕昇 JDK11.0.11
在对约 60G 大小的堆进行扫描时,可以看到 JDK8 并行扫描的平均收益在 26%左右,JDK11 并行扫描的平均收益在 31%左右。
G1 GC 实现 NUMA-Aware 特性(毕昇 JDK8)
背景
在 NUMA 架构下,跨 NUMA 节点操作内存相比本 NUMA 节点操作内存时延会成倍增加。OpenJDK 社区在 JDK14 中合入了 G1 GC NUMA-Aware 特性[4],可以让 JAVA 用户线程尽可能的操作本 NUMA 节点上的内存,可以提高 G1 GC 在 NUMA 架构下的处理性能,但低版本的 JDK8 和 JDK11 不支持该特性。
实现
毕昇 JDK 以前已将社区高版本中的 G1 NUMA-Aware 特性合入到了 11.0.8,此次将该特性回合到 8u292,有效提高 G1 GC 在 NUMA 架构下的处理性能。具体的实现方式为:在配置的 NUMA node 节点(numactl 可以配置,不配置就是所有节点)上,均匀分配 G1 Region,在 Young 区(Eden 和 Survivor)申请 Region 的时候优先选择本节点的 Region。
用户只需要通过打开 UseNUMA 参数即可使用此特性,如下所示:
-
-XX:+UseG1GC –XX:+UseNUMA
性能测试
SPECjbb 2015 是业界通用的 Java 性能的基准测试[5],测试结果主要分为 Max 和 Critical,其中 Max 是指最大吞吐量,Critical 是指在在限制响应时间下的吞吐量。这里采用 SPECjbb 对该特性进行测试。
测试环境:
-
CPU:Kunpeng-920,96核
-
OS:openEuler20.03
-
内存:384G
-
JDK: 毕昇JDK1.8.0_292
-
SPECjbb配置:GROUP_COUNT=1,TI_JVM_COUNT=4
SPECjbb 的测试结果如下,可以看到与不开启 NUMA 相比,开启 NUMA 后 的性能平均提升 20%+.
G1 GC NUMA-Aware 优化(毕昇 JDK11)
背景
毕昇 JDK11 已在 11.0.8 版本支持 G1 GC Numa-Aware 特性,合入该特性后,G1 都尽量在线程所属的 NUMA node 上去分配内存,当线程所属 Node 上的内存不够分配或者在指定的遍历次数达到后,如果没有获取到所属 node 上的内存时就会随机从空闲的链表上取一个 region,而这种随机选择的不一定是最优的。
实现
上图以华为泰山 200 服务器为例,通过numactl --hardware
可以显示 node 间距离值信息,可以看到 node 自身的距离值是 10, node1 与 node2 的距离值是 16,node1 与 node3 的距离值是 32,数值越小,跨 node 的访存速度会更快。基于上面背景描述,毕昇 JDK11.0.11 在毕昇 JDK11.0.10 的基础上,对 G1GC NUMA-Aware 特性访存做了持续优化,通过在遍历 free region 链表时,记录到本 Node 的最小距离的 region,最终将距离本线程所属 Node 最小距离的 region 分配出去(包含本 Node 上的 region,距离为 10),实现内存访问的尽量最优化,达到提升业务性能目的。
用户只需要通过打开 UseNUMA 参数来使用此特性,如下所示:
-
-XX:+UseG1GC –XX:+UseNUMA
性能测试
测试环境与上述毕昇 JDK8 的 NUMA-Aware 测试环境相同。
SPECjbb 的测试结果如下,可以看到与毕昇 JDK11.0.10 相比,开启 NUMA 特性后,Critical 性能平均提升 9%,Max 性能无劣化。
Bug fixes
除了上面介绍的一些特性外,毕昇 JDK 还合入了社区高版本中的一些 bug fix 和优化的 patch,为用户提供稳定、高性能的毕昇 JDK。具体回合 patch 如下:
-
JDK8
-
8264640: CMS ParScanClosure misses a barrier
-
8266191: Missing aarch64 parts of JDK-8181872(C1: possible overflow when strength reducing integer multiply by constant)
-
8266929: Unable to use algorithms from 3p providers
-
8268427: Improve AlgorithmConstraints:checkAlgorithm performance
-
JDK11
-
8264640: CMS ParScanClosure misses a barrier
参考
[1] 毕昇 JDK8 下载:https://mirrors.huaweicloud.com/kunpeng/archive/compiler/bisheng_jdk/bisheng-jdk-8u292-linux-aarch64.tar.gz
[2] 毕昇 JDK11 下载:https://mirrors.huaweicloud.com/kunpeng/archive/compiler/bisheng_jdk/bisheng-jdk-11.0.11-linux-aarch64.tar.gz
[3] KAEProvider jmh 用例:https://gitee.com/openeuler/bishengjdk-8/tree/master/jdk/test/micro/org/openeuler/bench/security/openssl
[4]JEP 345: NUMA-Aware Memory Allocation for G1:https://openjdk.java.net/jeps/345
[5]SPECjbb 2015:https://www.spec.org/jbb2015/
交流群:
欢迎加入 Compiler SIG 交流群,一起交流编译器、虚拟机技术。或添加微信,回复”加群”,进入 Compiler SIG 交流群。
本文分享自微信公众号 – openEuler(openEulercommunity)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
{{m.name}}
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/72248.html