Dynamic adaptation to application sizes (DATAS) GC 策略
現在大家的 .NET 程序基本都部署在如 K8S 這種容器化場景下。出于節約資源的考慮,往往我們還會限制每個實例占用的資源。不知道大家發現沒有,在一些高并發的場景下,我們的程序會占用非常多的內存,內存遲遲不釋放,在某些極端情況下甚至會發生 OOM 。如果你搜索這個問題,大概率會找到一個答案,那就是在一些資源有限的環境請把 GC 改成 workstation 模式。更改為 workstation 模式后,內存占用高的情況確實有所好轉,但是同時也會影響服務的吞吐量。
到了 .NET8 其實我們還有另外一個 GC 的策略可以選擇,那就是 DATAS - Dynamic adaptation to application sizes 。它可以幫我們在內存占用跟吞吐量之間找到一個平衡。
首先讓我們回顧一下什么是 Workstation 跟 Server GC。
Workstation GC
工作站垃圾回收(Workstation GC)
定位:專為客戶端應用程序設計
- 默認場景:
獨立應用程序的默認GC類型
托管應用(如ASP.NET托管的應用)由宿主決定默認類型
- 運行模式:
并發模式(Concurrent GC):允許托管線程在垃圾回收期間繼續運行(.NET Framework 4及后續版本中由后臺GC取代)
非并發模式:執行垃圾回收時會暫停所有托管線程
Server GC
服務器垃圾回收(Server GC)
核心優勢:為需要高吞吐量和高可擴展性的服務端應用程序優化
- 典型特征:
為每個邏輯CPU創建獨立GC堆
采用更激進的堆擴展策略
適用于多核服務器環境
DATAS
了解了 Workstation 與 Server GC 的概念后,讓我們看看 DATAS 是怎么工作的。
動態適應應用規模的垃圾回收機制(DATAS GC)旨在根據應用程序的內存需求進行自適應調整。這意味著應用程序堆大小應與長期存活數據量大致成正比。如果在不同配置的機器上運行相同任務,堆大小應保持相同或相近;當工作負載減輕或加重時,堆大小會相應調整。
與之相比,服務器GC模式(Server GC)以提升吞吐量為目標,假設當前進程是機器上的主導進程。其觸發下次GC前的分配量基于吞吐量而非應用規模。只要內存可用,它會激進地擴展堆空間,導致相同進程在不同硬件配置的機器上運行時堆大小差異顯著(例如在核心數和內存更多的機器上堆會大幅增長)。即使工作負載大幅減輕,服務器GC也不一定會主動縮減堆空間。
DATAS GC尤其適合突發型工作負載,能根據負載需求(特別是需求下降時)調整堆大小。這對內存受限環境至關重要——當某些進程負載降低時可容納更多進程,同時也利于容量規劃。該功能在.NET 8中作為可選特性引入,并在.NET 9默認啟用。
實現原理
為實現應用規模自適應且保持性能,DATAS GC采取以下策略:
基于長期存活數據量設定觸發下次GC前的最大分配量,從而約束堆大小
基于吞吐量動態調整實際允許的分配量
彈性調整堆數量:初始僅使用單堆(多線程分配時可能引發等待,影響吞吐量),但會根據需求增減堆數量。這種混合模式兼具工作站GC(單堆)和服務器GC(按核心數分配堆)的優勢
執行完全壓縮式GC以防止內存碎片過高,進一步幫助控制堆大小
關注我的公眾號一起玩轉技術

QQ群:1022985150 VX:kklldog 一起探討學習.NET技術
作者:Agile.Zhou(kklldog)
出處:http://www.rzrgm.cn/kklldog/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

浙公網安備 33010602011771號