zgc介紹
zgc在JDK15中終於官宣能夠投入生產使用,官方博客的話就是穩定,高性能,低延時的gc。mysql
zgc的核心是一個併發垃圾回收器,其設計的目標是:算法
- 最大停頓時間是幾毫秒
- 停頓時間不會隨着堆變大而變大
- 堆範圍8mb-16tb
固然zgc也有其餘不少有用的功能例如:支持NUMA,支持NVRAM申請堆,類數據共享等等sql
本文主要討論其在openjdk15和graalVM21和openjdk11中的表現,關於其原理和其餘功能不做爲重點敘述。數據庫
準備工做
一.三個版本的jdk數組
1.openjdk15 2.graalvm21 3.openjdk11安全
二.jvm啓動jvm參數併發
1. -XX:ZCollectionInterval =1 -XX:-ZProactive 定時gc,關閉主動gcjvm
2. -XX:ZAllocationSpikeTolerance = 5 不設置定時gc,zgc根據本身算法進行gc 係數爲5性能
三.場景測試
測試應用:mysql分庫分表中間件
1. 1000個鏈接循環發送請求發送sql至不一樣版本jdk啓動的分庫分表中間件(限制單庫鏈接數-產線環境)
2. 2000個併發,用jmeter測試tps發送sql至中間件(不限制單庫鏈接數)
注: 場景 1 驗證客戶端感知(請求返回時間) 場景3 驗證TPS
測試結果:
jdk15(定時gc-場景1)
graalvm21(定時gc-場景1)
jdk11(定時gc-場景1)
jdk15(不定時gc-場景1)
graalvm21(不定時gc-場景1)
jdk11(不定時gc-場景1)
jdk15(定時gc-場景2)
graalvm(定時gc-場景2)
jdk11(定時gc-場景2)
jdk15(不定時-場景2)
graalvm21(不定時-場景2)
jdk11(不定時-場景2)
注:因爲是用公司機器進行測試,在進行不定時-場景2測試時,其餘應用訪問數據庫流量變大,因此本次測試結果TPS偏小,後又通過幾回測試,tps雖增大,可是仍小於定時-場景2,不影響測試結論。
結論:
cpu佔用率:
graalVm21 > openjdk11 > openjdk15
堆內存使用狀況
graalVm21 < openjdk15 ~ openjdk11
開始測試時出現大於200ms請求的次數(筆者所在項目關注的指標)
openjdk11 > graalvm21 > openjdk15
不定時GC JVM參數下,兩次GC間隔:
openjdk15 > graalvm21 > openjdk11
2000併發下tps 爲:
openjdk15 > graalvm21 ~ openjdk11
綜合比較: graalVm21 和 openjdk15 ZGC內存性能相關相差不大,可是openjdk15開始壓測時出現大於200ms請求量較少(即TTSP短),tps相對較高。
在本次測試中,非定時gc狀況下TPS小於定時gc狀況下tps
兩種JVM參數下GC停頓時間99線爲:
定時GC:0.845ms
非定時GC : 0.273ms
均不超過1ms
擴展:
通過本次測試,不由產生兩個疑問:
1.openjdk15 的zgc相較於11作了哪些優化
2.爲何定時gc下TPS比非定時gc下TPS高
問題1:通過一系列的測試和資料查找發現jdk11-15 zgc的相關優化以下(紅框內爲涉及本次測試優化):
1.zgc在jdk13時縮短了到達safepoint的時間(ttsp)
2.jdk14引入了安全點可識別數組分配(將初始化爲0期間的數組標記爲不可見根,任何大小的數組都不會影響TTSP)(不在截圖內,在jdk14官方博客中能夠找到相關優化介紹)
3.jdk12支持併發卸載類,而且進一步縮短了停頓時間
問題2:通過對gc日誌的分析得出:
ZGC初次標記和搬運階段定時GC平均時間小於非定時GC平均時間,由於定時GC初次標記階段須要標記的root相對較少,搬運對象也相對較少。
因此其stw相對較小。即TPS相對較高。
思考:
本次測試並不表明全部狀況下定時gc都比非定時gc更優。由於非定時gc狀況下,jvm會根據配置的係數來進行GC,當流量忽然增大,會增長gc次數,頻繁gc,當流量平穩時,會減小gc次數。是不一樣的GC策略,實際生產應用中還須要根據不一樣場景進行選擇。