畢昇 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 下載:http://mirrors.huaweicloud.com/kunpeng/archive/compiler/bisheng_jdk/bisheng-jdk-8u292-linux-aarch64.tar.gz

[2] 畢昇 JDK11 下載:http://mirrors.huaweicloud.com/kunpeng/archive/compiler/bisheng_jdk/bisheng-jdk-11.0.11-linux-aarch64.tar.gz

[3] KAEProvider jmh 用例:http://gitee.com/openeuler/bishengjdk-8/tree/master/jdk/test/micro/org/openeuler/bench/security/openssl

[4]JEP 345: NUMA-Aware Memory Allocation for G1:http://openjdk.java.net/jeps/345

[5]SPECjbb 2015:http://www.spec.org/jbb2015/

交流群:

歡迎加入 Compiler SIG 交流群,一起交流編譯器、虛擬機器技術。或新增微信,回覆"加群",進入 Compiler SIG 交流群。




本文分享自微信公眾號 - openEuler(openEulercommunity)。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。