畢昇 JDK 8u292、11.0.11 發佈!

語言: CN / TW / HK

2021 年 6 月 30 日,畢昇 JDK update Q2 版本正式發佈,下載方式見文末參考鏈接。該版本在同步 OpenJDK 社區 8u292/11.0.11 的基礎上,還包含如下更新,為用户提供高性能、可用於生產環境的 OpenJDK 發行版。

  1. 提供鯤鵬硬件加速的 KAEProvider 支持 DH,RSA 簽名等眾多算法(畢昇 JDK8)
  2. Jmap 並行掃描優化支持 CMS(畢昇 JDK8, 畢昇 JDK11)
  3. G1 GC 實現 numa-aware 特性(畢昇 JDK8)
  4. G1 GC numa-aware 優化(畢昇 JDK11)
  5. 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)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閲讀的你也加入,一起分享。