2021 年 9 月 30 日,畢昇 JDK update Q3 版本正式發(fā)布,本次發(fā)布將包含 X86_64 版本。此前,畢昇 JDK 只發(fā)布 Aarch64 版本,這可能會(huì)對(duì)運(yùn)維產(chǎn)生一定的影響,例如需要根據(jù)架構(gòu)構(gòu)建多個(gè)版本以包含不同架構(gòu)的 JDK,此次畢昇 JDK 同時(shí)發(fā)布 X86_64 版本以及 Aarch64 版本,將極大的方便用戶進(jìn)行構(gòu)建,降低維護(hù)多個(gè)版本的開銷。另外,X86_64 版本和 Aarch64 版本共源,所以 X86_64 版本也包含此前畢昇 JDK 團(tuán)隊(duì)在 Aarch64 上的功能和大部分優(yōu)化,在功能和性能方面,兩者幾乎無差異。歡迎用戶安裝使用,為產(chǎn)品帶來核心競爭力。
此次版本在同步 OpenJDK 社區(qū) 8u302/11.0.12 的基礎(chǔ)上,還包含如下更新,為用戶提供高性能、可用于生產(chǎn)環(huán)境的 OpenJDK 發(fā)行版。
PS 優(yōu)化——Introduce UsePSRelaxedForwardee to enable using relaxed CAS in copy_to_survivor_space(畢昇 JDK8,畢昇 JDK11)
G1 GC 優(yōu)化——Parallel Full GC for G1(畢昇 JDK8)
提供鯤鵬硬件加速的 KAEProvider(畢昇 JDK11)
支持按進(jìn)程 id 和時(shí)間戳生成 jfr 文件(畢昇 JDK8,畢昇 JDK11)
Bug fixes
1 PS:introduce UsePSRelaxedForwardee to enable using relaxed CAS in copy_to_survivor_space(畢昇 JDK8,畢昇 JDK11)1.1 背景
在 JDK 中 Parallel Scavenge 是一個(gè)高吞吐量 GC,使用非常廣泛。在 specjbb 測試中,PSPromotionManager::copy_to_survivor_space 中的 CAS 指令 CPU 占比非常高,主要為 releasebarrier 導(dǎo)致,分析 PS 邏輯后,CAS 沒必要使用 memory barrier,使用 relaxed 可以提高弱內(nèi)存模型架構(gòu)上 PS 的性能。
1.2 實(shí)現(xiàn)原理
PS 的主要邏輯如下:
由上述流程圖可以看到,CAS Fail 的線程不會(huì)去讀 forwardee 內(nèi)容,因此在弱內(nèi)存模型的 CPU 架構(gòu)上,即使 copy obj 和 CAS 亂序,也不會(huì)影響 CAS Fail 線程的正確性。
關(guān)于 work steal 場景,其他線程 steal 到的 obj 能否看到其內(nèi)容,這個(gè)是由 CAS 成功的 push 操作保證的,由于 push 操作底層實(shí)現(xiàn)有 release 語義,所以無正確性問題。
使用參數(shù):
UsePSRelaxedForwardee:試驗(yàn)特性開關(guān),默認(rèn)為 false,表示 PSPromotionManager::copy_to_survivor_space 中 CAS forwardee 使用 release 語義;打開則表示 CAS forwardee 的時(shí)候使用 relaxed(無任何 memory barrier),以在弱內(nèi)存模型 CPU 架構(gòu)上獲取更好性能。
1.3 性能測試
測試環(huán)境:
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 1
Core(s) per socket: 64
Socket(s): 2
NUMA node(s): 4
Vendor ID: 0x48
Model: 0
Stepping: 0x1
BogoMIPS: 200.00
L1d cache: 64K
L1i cache: 64K
L2 cache: 512K
L3 cache: 65536K
NUMA node0 CPU(s): 0-31
NUMA node1 CPU(s): 32-63
NUMA node2 CPU(s): 64-95
NUMA node3 CPU(s): 96-127
使用 specjbb2015 進(jìn)行測試,除 UsePSRelaxedForwardee 開關(guān)以外的測試參數(shù)如下:
-Xms50g -Xmx50g -XX:+UseParallelGC -XX:ParallelGCThreads=24 -XX:+UseLargePages -XX:LargePageSizeInBytes=2m -XX:+UseBiasedLocking -XX:+AlwaysPreTouch -XX:-UseAdaptiveSizePolicy
測試結(jié)果:
測試結(jié)果:從上圖可以看到,針對(duì) SPECjbb 的 critical,畢昇 JDK8 可以提升 15%,畢昇 JDK11 可以提升 28%
2 Parallel Full GC for G1. (畢昇 JDK8)2.1 概述
G1 Full GC 是完全的 STW,在此期間應(yīng)用程序線程完全沒有機(jī)會(huì)運(yùn)行,長時(shí)間停頓會(huì)造成用戶明顯的感知。因此,使用 G1 過程中應(yīng)盡量避免的 Full GC 的出現(xiàn),如果出現(xiàn)最好能縮短其時(shí)間。當(dāng)前 JDK 8u 中 G1 Full GC 完全采用串行,包括:
各階段之間,包括標(biāo)記存活對(duì)象、計(jì)算目標(biāo)對(duì)象的位置、更新引用的位置、移動(dòng)對(duì)象完成壓縮階段;
每個(gè)階段內(nèi);
完全的串行導(dǎo)致即使是在多核機(jī)器上也無法利用機(jī)器的強(qiáng)大性能縮短 Full GC 的(停頓)時(shí)間。
由于 G1 Full GC 基本算法的約束,雖然上面提到的四個(gè)階段之間無法并行化,但是各個(gè)階段內(nèi)卻可以通過優(yōu)化算法做到一定并行化,以達(dá)到縮短整體停頓時(shí)間的效果。本特性會(huì)將計(jì)算目標(biāo)對(duì)象的位置、更新引用的位置、移動(dòng)對(duì)象完成壓縮三個(gè)階段盡量做到階段內(nèi)的并行化。(標(biāo)記存活對(duì)象階段的并行化后續(xù)也會(huì)支持)
開啟本特性后,可以明顯降低 G1 Full GC 的平均停頓時(shí)間。本特性屬于通用特性,適用于 Aarch64、X86 平臺(tái)。
2.2 實(shí)現(xiàn)原理
2.2.1 并行 Full GC 基本算法
如下列出了并行 Full GC 算法與串行 Full GC 算法的主要差異點(diǎn):
將整個(gè)堆分成不同的 heap region set 交給各個(gè) GC 線程分別處理,盡量減少 GC 線程間同步、競爭;
G1 Full GC 現(xiàn)有實(shí)現(xiàn)是將整個(gè)堆向一個(gè)方向(目標(biāo)地址)壓縮;要做到并行化,并減少并行 GC 線程間的交互、競爭,有效的方式是每個(gè) GC 線程有自己壓縮的方向(目標(biāo)地址)。
大對(duì)象的特殊處理:在計(jì)算目標(biāo)對(duì)象位置并行階段結(jié)束后,才能釋放 free 的 humongous region;
2.2.2 計(jì)算目標(biāo)對(duì)象位置階段的并行化
計(jì)算目標(biāo)對(duì)象位置階段主要負(fù)責(zé)
根據(jù)標(biāo)記信息設(shè)置對(duì)象的 forwardee。
釋放沒有被標(biāo)記的 humongous regions。
Forwardee 的設(shè)置需要預(yù)先知道目標(biāo)地址,該目標(biāo)地址是通過 Compaction Point 維護(hù)著。在遍歷 heap region 時(shí)每當(dāng)發(fā)現(xiàn)一個(gè)新的標(biāo)記的對(duì)象,就將 Compaction Point 里記錄的目標(biāo)地址設(shè)置為該對(duì)象的 forwardee,然后再將 Compaction Point 里記錄的目標(biāo)地址加上對(duì)象的大小,作為下次 forwardee 設(shè)置的值。如此往復(fù),直至每一個(gè)標(biāo)記的對(duì)象都被 forwarded。
并行地設(shè)置對(duì)象的 Forwardee 是通過 1)隔離各個(gè) GC 線程的遍歷的 heap region,2)隔離各個(gè) GC 線程要為 forwardee 設(shè)置的目標(biāo)地址來達(dá)成的。具體實(shí)現(xiàn)是,1)通過標(biāo)記 region 來隔離各個(gè) GC 線程遍歷的 heap regions,2)通過為每個(gè) GC 線程維護(hù)一個(gè) Compaction Point 來隔離 forwardee 的設(shè)置。可以理解為將整個(gè) heap 被分成了 N 份(GC 線程個(gè)數(shù)為 N),每一份由一個(gè) GC 線程負(fù)責(zé),各個(gè)線程盡量互不干擾地工作。
除此之外,每個(gè) GC 線程的 Compaction Point 還負(fù)責(zé)收集屬于該 GC 線程的 regions、humongous regions,以便后續(xù)(壓縮階段)處理。
Free 的大對(duì)象在計(jì)算目標(biāo)對(duì)象位置階段就會(huì)被釋放。由于大對(duì)象的特殊性(可能包括多個(gè) heap region)加之多個(gè) GC 線程在同時(shí)工作,需要對(duì)其進(jìn)行一些特殊處理:如,在計(jì)算目標(biāo)對(duì)象位置并行階段結(jié)束后,才能釋放 free 的 humongous region,以避免多個(gè) GC 線程訪問同一個(gè)大對(duì)象的不同 region 時(shí)可能面臨的數(shù)據(jù)不一致問題。
2.2.3 更新引用位置階段的并行化
更新引用位置階段主要負(fù)責(zé)根據(jù)對(duì)象的 forwardee 信息更新所有引用。
此階段的并行化比較簡單,因?yàn)樾枰乃行畔⒍贾辉趯?duì)象頭中(forwardee),并行化和串行化的算法差別很小,不同點(diǎn)只是每個(gè) GC 線程要標(biāo)記屬于自己處理范圍的 heap region。
2.2.4 移動(dòng)對(duì)象完成壓縮階段的并行化
移動(dòng)對(duì)象完成壓縮階段主要負(fù)責(zé)根據(jù)對(duì)象的 forwardee 信息進(jìn)行壓縮。
每個(gè) GC 線程都有屬于自己的 Compaction Point,在計(jì)算目標(biāo)對(duì)象位置階段 Compaction Point 中收集了需要該 GC 線程壓縮的 region 的集合。對(duì)于單個(gè) GC 線程來說,整個(gè)過程與串行差別不大,只是需要從自己的 Compaction Point 中取出 regions,進(jìn)行壓縮。
使用參數(shù):
本特性需要通過 VM option -XX:+G1ParallelFullGC 顯示打開,默認(rèn)為關(guān)閉。
注意,本特性會(huì)帶來如下 JVM 停頓時(shí)間上的收益:
降低單次 G1 Full GC 的停頓時(shí)間;
降低總的 G1 Full GC 的停頓時(shí)間;
但是,有可能會(huì)增加 G1 Full GC 的頻率。所以,當(dāng)降低 JVM 的停頓時(shí)間是應(yīng)用程序的性能調(diào)優(yōu)目標(biāo)之一時(shí),且 G1 Full GC 是停頓原因之一時(shí),適用于打開 G1ParallelFullGC VM Option,降低單次平均、總的停頓時(shí)間。
2.3 性能測試
測試套:Dacapo
測試參數(shù):
JVM:-Xmx1g -Xms1g -XX:ParallelGCThreads=$N
Dacapo:-t 4 --iterations 5 --size huge --no-pre-iteration-gc h2
下面分別給出了并行 GC 線程數(shù)量分別為 4、16 時(shí) Full GC 停頓時(shí)間的數(shù)據(jù)
N == 4
N == 16
測試結(jié)果:受益(STW 時(shí)間減少)基本在 16%~40%。
3 提供鯤鵬硬件加速的 KAEProvider(畢昇 JDK11)該特性已在早期的畢昇 JDK 8u282 中支持,詳見2021 年畢昇 JDK 的第一個(gè)重要更新來了,并在 8u292 版本中對(duì)其功能進(jìn)行完善,詳見畢昇 JDK 8u292、11.0.11 發(fā)布!, 此次將在畢昇 JDK11 中對(duì)該特性進(jìn)行支持。
3.1 實(shí)現(xiàn)原理和性能測試
實(shí)現(xiàn)原理和性能測試請(qǐng)參考鯤鵬硬件加解密特性詳解。 但由于 JDK11 引入了模塊系統(tǒng),因此用戶使用時(shí)需要將 KAEProvider 所在的模塊(jdk.crypto.kaeprovider)進(jìn)行導(dǎo)出,如下為畢昇 JDK11 中 KAEProvider 相關(guān)的文件:
具體導(dǎo)出命令可參考如下格式:
編譯:javac --add-modules jdk.crypto.kaeprovider --add-exports=jdk.crypto.kaeprovider/org.openeuler.security.openssl=ALL-UNNAMED DHTest.java
運(yùn)行:java --add-modules jdk.crypto.kaeprovider --add-exports=jdk.crypto.kaeprovider/org.openeuler.security.openssl=ALL-UNNAMED DHTest
4 支持按進(jìn)程 id 和時(shí)間戳生成 jfr 文件(畢昇 JDK8,畢昇 JDK11)4.1 說明
該特性用來擴(kuò)展 JFR 文件名,支持在文件名中加入進(jìn)程號(hào)或時(shí)間戳或兩者都加,當(dāng)用戶在環(huán)境上生成多個(gè) jfr 文件時(shí),該特性可以幫助用戶根據(jù)需要快速定位到所需的文件。
4.2 功能測試
未合入此特性:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=10s,filename=myrecording%t.jfr While
合入此特性:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=10s,filename=myrecording%t.jfr While
5 Bug fixes除了上面介紹的一些特性外,畢昇 JDK 還合入了社區(qū)高版本中的一些 bug fix 和優(yōu)化的 patch,為用戶提供穩(wěn)定、高性能的畢昇 JDK。具體回合 patch 如下:
JDK8
8197387:jcmd started by “root” must be allowed to access all VM processes 允許通過 root 啟動(dòng)的 jcmd 訪問環(huán)境上任意的 JVM 進(jìn)程,默認(rèn)情況下,進(jìn)程只能被啟動(dòng)該進(jìn)程的用戶通過 jcmd 訪問。
8069191:moving predicate out of loops may cause array accesses to bypass null check 修復(fù) c2 在 aarch64 上可能會(huì) crash 的 bug
8167014: jdeps: Missing message: warn.skipped.entry 該修復(fù)可以解決通過 jdeps 解析特定的 jar 包出現(xiàn)的 Missing message: warn.skipped.entry 錯(cuò)誤
8268453: sun/security/pkcs12/EmptyPassword.java fails with Sequence tag error 該修復(fù)可以解決當(dāng)對(duì)密碼為空的 KeyStore 進(jìn)行解析時(shí),可能會(huì)出現(xiàn)的 java.io.IOException: Sequence tag error 問題
8202142:jfr/event/io/TestInstrumentation is unstable JDK 自帶用例修復(fù)
8143251:HeapRetentionTest.java Test is failing on jdk9/dev 該修復(fù)可以解決 G1 GC 在特定場景下導(dǎo)致進(jìn)程假死的問題
8183543:Aarch64: C2 compilation often fails with “failed spill-split-recycle sanity check” 修復(fù) C2 編譯器在某些場景下編譯方法時(shí)報(bào)failed spill-split-recycle sanity check錯(cuò)誤,導(dǎo)致方法被解釋執(zhí)行,進(jìn)而造成應(yīng)用程序性能下降的問題
JDK11
8268427: Improve AlgorithmConstraints:checkAlgorithm performance 該 patch 可以提升 TLS 的握手性能
8257145: Performance regressionwith -XX:-ResizePLABafter JDK-8079555 該 patch 可以修復(fù)使用 G1 GC 后,HBase 性能下降的問題,詳細(xì)原理可參考畢昇 JDK 以前的文章JDK 從 8 升級(jí)到 11,使用 G1 GC,HBase 性能下降近 20%。JDK 到底干了什么?
8247691:[aarch64] Incorrect handling of VM exceptions in C1 deopt stub/traps 該修復(fù)可以解決 C1 編譯器生成指令過程中使用錯(cuò)誤的寄存器,進(jìn)而導(dǎo)致進(jìn)程 Crash 的問題
編輯:jq
評(píng)論