當前位置: 妍妍網 > 碼農

JDK 21:GC 不斷改進,效能更上一層樓

2024-03-05碼農

來源:kstefanj.github.io/2023/12/13/jdk-21-the-gcs-keep-getting-better.html

👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 贈書福利

全棧前後端分離部落格計畫 1.0 版本完結啦,2.0 正在更新中 ... , 演示連結 http://116.62.199.48/ ,全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了219小節,累計35w+字,講解圖:1492張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,

  • 簡介

  • 選擇 GC

  • 進展

  • 吞吐量

  • 延遲

  • 記憶體開銷

  • 升級並嘗試分代 ZGC

  • 隨著 2023 年秋季釋出的 JDK 21,現在有一個新的 LTS 版本可以進行基準測試並生成一些 GC 效能圖表。JDK 21 和自 JDK 17 以來的其他版本提供了一系列值得註意的功能,如虛擬執行緒、用於switch 的模式匹配和分代 ZGC。讓我們看看它的表現如何。

    簡介

    當在不同的 JDK 版本之間進行效能比較時,很難確定哪些功能帶來了某種效能提升。但很容易看出,自 JDK 8 以來,整個 Java 平台在效能上已經顯著提升。在這篇文章中,我使用 SPECjbb® 20151 來展示效能的提升。這是一個眾所周知的標準基準測試,非常適合展示對GC的改進。這主要是因為該基準測試提供了兩個得分:

  • max-jOPS :原始吞吐量

  • critical-jOPS :在延遲約束下的吞吐量

  • GC 的改進將同時提高這兩個得分,但對於受延遲約束的得分的改進更加與 GC 的改變密切相關。基本上,較短的暫停將獲得更好的得分。對於原始吞吐量得分來說,JIT 和 Java 平台的其他部份的改進也起到了作用。

    在基準測試時沒有進行太多調優,但我設定了一個固定的堆大小為 16 GB,並啟用了大頁,並確保在執行基準測試之前將它們分頁。我希望結果能夠反映出隨插即用的行為,但是像這樣的配置可以獲得公平一致的結果。

    選擇 GC

    Oracle 支持 4 種不同的 GC,它們都有不同的用途。在這篇文章中,我不包括 Serial GC,因為它不適用於我使用的基準測試。Serial GC 的主要重點是低開銷,主要適用於記憶體和 CPU 資源有限的用例。在這次比較中,我們將重點介紹以下 GC:

  • G1 :自JDK 9起的預設收集器,註重延遲和吞吐量之間的平衡

  • Parallel :以吞吐量為導向的收集器,可能會出現較長的最壞情況延遲

  • Z :超低延遲的替代方案,完全並行,暫停時間在毫秒級別以下

  • 使用哪種 GC 取決於應用程式最關註的方面。每種 GC 都有最佳的替代方案,並且沒有一種 GC 可以在所有用例中都表現最佳。

    進展

    如果回顧 JDK 8 以來的進展,G1 和 Parallel 的改進在各個方面都是相當驚人的。這兩個收集器在各個方面都有所改進。它們的暫停時間更短,使用的記憶體更少,吞吐量比以往任何時候都要好。ZGC 的時間沒有那麽長,並且在這篇文章中,我主要關註透過使 ZGC 成為分代收集器帶來的改進。

    本文中的圖表分別比較了不同的收集器。主要原因是根據堆大小的配置,結果對於某個收集器更有利。透過這樣做,我們可以關註所有 GC 的巨大進步,而不是試圖給出最佳的 GC。

    比較包括 JDK 8、JDK 17 和 JDK 21 的 G1 和 Parallel。對於 ZGC,我選擇的三個數據點是 JDK 17、JDK 21 和 JDK 21 中的分代 ZGC。由於 JDK 17 是 ZGC 完全支持的第一個 LTS 版本,所以回顧更早的版本並沒有太多意義。

    吞吐量

    就原始吞吐量效能而言,與 JDK 17 相比,自 JDK 17 以來的改進並不是很大,但仍有輕微增加。但是,在下面的圖表中,有兩件事情真正值得關註。首先,JDK 8 和最新 JDK 之間的顯著差異對於G1和Parallel來說。從效能的角度來看,離開 JDK 8 從來沒有比現在更有益。

    圖片

    第二個值得註意的是使用分代 ZGC 時看到了有 10% 的提升。ZGC 中的新分代支持使其能夠更高效地回收記憶體,不需要考慮整個堆的每個 GC。其效果是在執行 GC 工作時消耗的 CPU 資源更少,這些資源可以用於應用程式,從而提高其效能。

    延遲

    對於延遲得分,情況基本上是一樣的。G1 和 Parallel 在 JDK 8 和 JDK 17 之間取得了巨大的進展,但最佳結果仍然是在 JDK 21。值得註意的是,在 JDK 8 和 JDK 17 之間進行了超過 7 年的創新,而在 JDK 17 和 21 之間,只有兩年。相比之下,較短的時間及 GC 的成熟,使得在這樣大型基準測試中很看到顯著的進展。

    圖片

    將分代引入 ZGC 仍然可以看到在分代 ZGC 和傳統模式之間的顯著差異,這非常好。值得註意的是,大部份的改進來自於吞吐量得分的提高。這兩種 ZGC 模式之間的暫停時間差異不大,它們都遠低於 1 毫秒。然而,當考慮最壞情況的延遲時,與傳統模式相比,分代 ZGC 相比之下顯得更好一些。

    圖片

    對於 G1 和 Parallel,暫停時間並沒有發生大的變化。我們在G1上花費了更多時間,在這裏,透過檢視更高百分位的暫停,我們可以看到我們已經成功地減少了幾毫秒的時間。

    記憶體開銷

    最後一個圖表比較了在固定負載下執行基準測試時的峰值本機記憶體開銷。就這個角度來看,Parallel 非常穩定,我們沒有花費任何時間來進一步最佳化它。另一方面,對於 G1,我們在過去的十年中已經成功地消除了許多低效性,並且在 JDK 20 中,我們將 G1 改為只需要一個標記位圖而不是兩個。由此節省下來的資源是顯著的,在這個基準測試中,G1 現在是最節省記憶體的收集器。

    圖片

    對於分代 ZGC,我們可以清楚地看到為了在這個基準測試中獲得更好的延遲和吞吐量而做出的權衡。代價是更高的本機記憶體消耗。為了有效地實作分代支持,我們需要跟蹤從老年代到新生代的指標。這稱為記憶集,並且它們占用記憶體。在處理多個代時,我們還需要一些其他後設資料所需的記憶體。盡管如此,在大多數情況下,與傳統 ZGC 相比,使用分代 ZGC 時總體記憶體消耗更低,因為它不需要處理給定工作負載所需的堆的大小。因此,額外的本機記憶體使用通常可以透過使用較小的堆來節省,並且仍然可以獲得更好的整體效能。

    升級並嘗試分代 ZGC

    就像上面看到的那樣,與 JDK 8 相比,JDK 21 的效能顯著提高。因此,如果你還在使用 JDK 8,應該開始考慮升級。在升級時,同時重新評估要使用的 GC 也是一個很好的時機。如果遷移到 JDK 21,我強烈建議嘗試使用分代 ZGC。在 JDK 21 中, ZGC 有分代版本和傳統模式都可用,要使用分代版本,需要指定下面兩個選項:

    -XX:+UseZGC -XX:+ZGenerational

    好書推薦

    小白學Python編程的入門經典教程:知識講解+老師答疑+上機實訓+思考與練習+綜合實戰+ChatGPT全能助手,零基礎學會Python既快速又簡單。

    學會構建高品質的提示指令,掌握利用人工智慧工具的藝術,成為與AI交流的高手。


    👉 歡迎 ,你將獲得: 專屬的計畫實戰 / Java 學習路線 / 一對一提問 / 學習打卡 / 贈書福利

    全棧前後端分離部落格計畫 1.0 版本完結啦,2.0 正在更新中 ... , 演示連結 http://116.62.199.48/ ,全程手摸手,後端 + 前端全棧開發,從 0 到 1 講解每個功能點開發步驟,1v1 答疑,直到計畫上線。 目前已更新了219小節,累計35w+字,講解圖:1492張,還在持續爆肝中.. 後續還會上新更多計畫,目標是將Java領域典型的計畫都整一波,如秒殺系統, 線上商城, IM即時通訊,Spring Cloud Alibaba 等等,


    1. 

    2. 

    3. 

    4. 

    最近面試BAT,整理一份面試資料Java面試BATJ通關手冊,覆蓋了Java核心技術、JVM、Java並行、SSM、微服務、資料庫、數據結構等等。

    獲取方式:點「在看」,關註公眾號並回復 Java 領取,更多內容陸續奉上。

    PS:因公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下在看,加個星標,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。

    「在看」支持小哈呀,謝謝啦