利用分代 ZGC 實現最佳臨時物件管理
一、簡介
管理臨時物件是 Java 虛擬機器最佳化中的關鍵效能因素。隨著 Java 21 中引入分代 ZGC(Z 垃圾收集器)(現已在 Java 22 中提供),我們進入了記憶體管理的新時代,以有效地處理短期物件。
在本教程中,我們將詳細探討分代 ZGC 並討論它如何增強臨時物件的管理。我們將展示它如何有助於 JVM 效能的整體提升。最後,我們將分享一個可以從我們新發現的知識中受益的實際用例。
2. Java中的臨時對象
臨時物件或短壽命物件是在程式執行期間建立的、壽命較短的物件。
一般來說,此類物件是中間結果、方法參數或臨時資料結構。在許多 Java 程式中,所有物件的很大一部分都屬於這一類。在涉及頻繁方法呼叫、臨時計算或快速資料轉換的應用程式中尤其如此。
作為範例,我們將考慮 Java 中臨時物件的生命週期,特別是在 Web 請求的上下文中。這包括它們在客戶端-伺服器互動期間的建立、處理和最終處置。
客戶端首先透過向伺服器發送HTTP請求來與伺服器進行通信,該請求提示伺服器產生要處理的臨時請求物件。當伺服器處理請求時,它可能會建立額外的臨時物件用於計算和資料管理(例如存取或修改作為臨時物件保存的會話資料)。
完成後,伺服器將封裝在臨時回應物件中的 HTTP 回應傳回給客戶端。最後,一旦收到回應,伺服器就會銷毀請求期間產生的臨時物件以釋放記憶體。
下圖展示了 Web 請求上下文中臨時物件的生命週期:
它概述了 Web 請求期間臨時物件生命週期所涉及的步驟,從初始使用者操作到處理後臨時物件的清理。
3、ZGC的演變
從 Java 11 開始的Z 垃圾收集器是 JVM 垃圾收集演變過程中的最新里程碑。 ZGC 具有低延遲和可擴展性的特點,使其成為低延遲伺服器工作負載的好選擇。
每個後續的 Java 版本都透過額外的優化增強了 ZGC。 2023 年 4 月,經過預覽後,Java 21 中推出了 Generational ZGC,以改進臨時物件管理。
4. 分代ZGC如何運作
**分代ZGC將堆分為兩段:一段用於新創建的物件(年輕代),另一段則用於生命週期較長的物件(老年代)。
**
4.1.對象分配和年輕代收集
年輕物件最初分配在 Z 世代垃圾收集器 (ZGC) 的年輕世代。它是為短壽命物件量身定制的記憶體區域。
年輕一代的收集頻率比老一代高得多。這意味著可以從不再使用的物件中快速回收記憶體。
**4.2.**優化並發收集
新一代的收集過程使用並發標記和疏散技術。這種雙重方法允許 ZGC 在應用程式運行時標記有資格回收的物件。
減少對應用程式執行緒的重複中斷可以降低應用程式延遲並提高效能敏感度。
4.3.物件升級和動態閾值
在年輕代中經歷了幾個收集週期後,物件可以晉升到老年代。這種機制將生命週期較短的物件與壽命較長的物件分開。 ZGC根據觀察到的物件生命週期分佈動態調整生命週期閾值。
升級閾值決定了物件何時應從年輕代升級到老年代。這種靈活性僅提升那些需要長期儲存的對象,進一步有助於優化記憶體使用。
4.4.老一輯系列
老一代的收集頻率低於年輕代,因為它主要包含在多個垃圾收集週期中倖存下來的長壽命物件。當老年代發生收集時,它的目的是從未使用的物件中回收記憶體。
由於其他應用程式部分的引用,這些物件可能在記憶體中保留的時間更長。老年代集合與年輕代集合類似,也使用並發技術。這可以確保當垃圾收集器回收未使用的記憶體時,應用程式執行緒能夠以最小的中斷繼續運行。
5. 視覺表現
為了更好地理解分代 ZGC 的機制,讓我們可以視覺化這個過程。
物件在年輕代中分配,通常使用並發標記和疏散技術來收集。這種頻繁的分配意味著我們可以快速從臨時物件中回收內存,這有助於保持低延遲和高效能。
那些多次在集合中倖存下來的物件將被移至舊一代,在那裡回收記憶體的頻率較低。此演算法根據物件生命週期自動調整升級閾值,優化長生命週期物件的記憶體管理。
6. 臨時物件的效能影響
分代 ZGC 的引入對於創建許多臨時物件的應用程式具有重大影響。
6.1.減少 GC 開銷
分代 ZGC 為 Java 應用程式帶來了高效能,特別是在管理臨時物件方面。因此,GC 開銷更少。
透過在大多數短命對象所在的年輕代中執行工作,分代 ZGC 可以快速回收內存,而無需執行昂貴的完整堆收集。這會導致花費在垃圾收集上的時間更少,而將更多的時間用於實際應用程式處理。
6.2.提高吞吐量
世代 ZGC 的另一個好處是提高了吞吐量。內部基準測試表明,與非一代前代產品相比,吞吐量提高了 10%。
處理大量資料或處理大量並發操作的應用程式將從這項改進中受益最多。因此,應用程式可以在更短的時間內處理更多的工作,通常不需要額外的運算資源。
6.3.減少暫停時間
當涉及 P99 暫停時間時,分代 ZGC 將應用程式回應速度提高了約 10%-20%。對於低延遲或恆定反應時間是關鍵成功因素的應用程式來說,暫停時間的減少非常重要。
對於股票市場套利的即時交易系統或延遲敏感的 Web 服務等應用程式來說,情況確實如此。在這種情況下,最大限度地減少暫停時間的停止世界收集器對於維持應用程式回應能力至關重要。這在重負載或高峰使用期間變得尤其重要。
6.4.高效率的記憶體回收
由於分代 ZGC 在回收記憶體方面比任何其他 GC 方法都更有效,因此它降低了在重分配負載下出現記憶體不足錯誤的可能性。透過密切追蹤短壽命物件的生命週期,GC 可以更積極地提升它們。
這使得未使用的記憶體可以更快地回收,從而為新的分配提供空間。此行為對於創建大量臨時物件的高分配率應用程式尤其重要。它有助於保持 GC 的延遲影響可預測,並防止記憶體耗盡導致的崩潰。
6.5.概括
下表總結了使用分代 ZGC 的臨時物件的效能影響:
方面 | 描述 | 影響 |
---|---|---|
減少 GC 開銷 | 分代 ZGC 透過專注於年輕世代中的短命對象來快速回收內存 | 垃圾收集花費的時間更少,應用程式時間更多 |
提高吞吐量 | 與非一代前代產品相比,吞吐量提高了 10% | 應用程式在更短的時間內處理更多的工作 |
減少暫停時間 | 低延遲應用程式的 P99 暫停時間減少 10-20% | 提高應用程式回應能力,這對於即時應用程式至關重要 |
高效率的記憶體回收 | 有效的記憶體回收減少記憶體不足錯誤 | 幫助管理高分配率,防止記憶體耗盡 |
上表顯示了分代 ZGC 在效能敏感的應用程式中管理臨時物件的優勢。
7. 使用案例:利用即時數據進行高頻交易
在高頻交易(HFT)中,速度至關重要。每秒處理數百萬個市場數據點,產生交易,系統執行快速計算。此處理提供臨時對象,例如交易訂單和市場快照,這些對象可能僅存在很短的時間。
7.1.世代 ZGC 如何提供協助
分代 ZGC 幾乎在創建這些短暫物件後立即收集它們,從而有助於避免記憶體開銷。
ZGC 引擎在背景運行,不會出現任何交易暫停。即使電子交易中的一微秒暫停也可能意味著錯過有利可圖的交易。
7.2.提高吞吐量
隨著資料快速進入,系統必須在不減慢速度的情況下處理大量資料。分代 ZGC 會在臨時物件累積時盡快清除它們,確保記憶體為下一輪計算做好準備。因此,即使市場繁忙,系統也會繼續前進。
7.3.避免記憶體崩潰
高頻交易平台每秒產生數百萬個物件。記憶體管理必須高效,以防止系統記憶體不足而崩潰。
當短期物件被丟棄時,ZGC 會不斷釋放空間。
7.4.隨市場擴展
隨著交易量的增加,系統必須在不損失效能的情況下處理更多資料。該平台可透過世代 ZGC 輕鬆擴展,有效消耗內存,即使工作負載增加一倍或三倍也是如此。
8. 優化分代 ZGC 的應用
我們應該遵循一些最佳實踐來充分利用分代 ZGC 的潛力,特別是在處理臨時物件方面。
8.1.重新評估激進的對像池
物件池是最常見的最佳化,其中物件被重複使用而不是創建新物件來優化記憶體和 GC 消耗。然而,由於分代 ZGC 可以有效地處理臨時對象,因此可能不再需要積極的對像池,甚至可能導致效能問題。
8.2.識別對象分配模式
分析工具可協助識別產生過多臨時物件的程式碼部分。可視化此過程有助於理解和優化您的應用程式。我們可以使用 JDK Mission Control、VisualVM 或 JProfiler 等分析工具來收集即時物件分配情況。我們可以將序列圖視覺化以進行分析:
開發人員啟動分析來監視物件分配,提示分析器偵測應用程式程式碼並收集資料。然後,開發人員分析報告以識別熱點並相應地優化程式碼。
8.3.調整分代 ZGC 的堆疊大小
考慮堆大小調整很重要。我們可以調整堆疊大小,以便針對我們的特定工作負載在年輕代和老年代大小之間找到適當的平衡。下圖顯示了堆大小調整的流程圖:
我們首先使用預設堆大小運行應用程序,並監視效能指標以檢查臨時物件分配情況。如果偵測到高分配,我們會調整年輕代大小並重新運行應用程式。我們繼續這個過程,迭代地細化堆大小,直到確定最佳配置。
8.4.監控和調整垃圾收集
持續監控有助於微調 GC 行為以提高應用程式效能。 JDK Flight Recorder (JFR) 和 J DK Mission Control (JMC) 等工具可協助監控 GC 行為並提高效能。我們可以視覺化 GC 監控和調整的序列圖:
開發人員啟用 GC 日誌記錄並啟動應用程序,從而允許記錄和分析垃圾收集事件以識別效能問題。根據此分析,開發人員調整 GC 參數並重新啟動應用程式以應用最佳化。
9. 未來的方向
隨著世代 ZGC 的成熟,我們可以期待進一步的最佳化和功能:
- 自適應代大小調整 –更複雜的演算法,用於根據應用程式行為動態調整年輕代和老年代的大小
- 增強的預測收集 –改進啟發式方法,用於預測何時觸發每一代的收集
- 與 JIT 最佳化整合 –加強 GC 和 JIT 編譯器之間的合作,以實現更好的物件分配和管理
- 針對特定物件類型的專門處理 – Java 應用程式中短期物件常見模式的潛在最佳化
10. 結論
在這篇文章中,我們看到Generational ZGC是JVM垃圾回收技術的重要創新。它建立在分代假設的基礎上,更有效地收集短壽命物件的垃圾。這可以提高各種 Java 應用程式的效能。
吞吐量、延遲和整體應用程式效能方面的提升是考慮在現代 Java 部署中使用分代 ZGC 的令人信服的理由。當存在大量臨時物件分配時尤其如此。