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
![]()
![]()
默认 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 进行合并。具体包含内容如下:
![图片]()
![图片]()
![]()
![图片]()
用户可通过在 jmap -histo 后增加 parallel 参数来使用此特性,如下所示:
-
jmap -histo:live,parallel=3 pid : 指定并行线程数为 3
-
jmap -histo:live,parallel=0 pid : 使用当前系统可支持的并行线程数(-XX:ParallelGCThreads)
-
jmap -histo:live,parallel=1 pid : 使用原有的串行扫描
性能测试
测试环境:
在对约 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 参数即可使用此特性,如下所示:
性能测试
SPECjbb 2015 是业界通用的 Java 性能的基准测试[5],测试结果主要分为 Max 和 Critical,其中 Max 是指最大吞吐量,Critical 是指在在限制响应时间下的吞吐量。这里采用 SPECjbb 对该特性进行测试。
测试环境:
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 参数来使用此特性,如下所示:
性能测试
测试环境与上述毕昇 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
参考
[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 交流群。
![]()