前言
.NET 中GC管理你服務的內存分配和釋放,GC是運行公共語言運行時(CLR Common Language Runtime)中,GC可以幫助開發人員有效的分配內存和和釋放內存,大多數情況下是不需要去擔心的,但是有時候服務總是是出現莫名的問題,所以還是有必要了解一下GC的基礎知識的。這裏就不介紹內存方面的知識了。
GC回收過程
GC
將對象分為大對象和小對象,如果對象的大小大於或者等於85000byte
將被視為大對象,大對象會被分配到到(LOH) Large Object Heap
中去。
GC
有一個代數的概念Generation
,分為三代
-
Generation 0
: 0代,這裏面都是生命周期很短的對象,比如臨時變量,當你new一個對象的時候該對象都會在Generation 0
中,這裏的對象將很快的被GC回收,但是當你new的是一個大對象的時候它會直接進去大對象堆(LOH) -
Generation 1
: 1代,這一代包含的也基本是生命周期很短的對象。它是短期對象和長期對象之間的緩衝區。 -
Generation 2
: 2代,這一代包含的都是生命周期長的對象,它們都是從1代和2代中選拔出來的,LOH
屬於2代。
當分配的對象使用的內存超出了GC
的閾值時回收就會開始。閾值是隨着服務的運行GC
自己調整的。或者直接調用GC.Collect
方法也可以開始回收。
回收開始時GC
會開始循環遍歷Generation 0
中的所有對象並標記所有對象是活動對象還是非活動對象,標記完成後會更新活動對象的引用。最後會回收非活動對象佔用的內存,並把活動對象壓縮后移動到Generation 1
中,Generation 1
中的或對象在移動到Generation 2
是默認不會被壓縮的,因為複製大的對象會導致性能的下降。可以通過GCSettings.LargeObjectHeapCompactionMode
來配置壓縮LOH
。
GC的回收類型
GC 回收有兩種類型,WorkStation GC
(工作站)和Server GC
(服務器),.Net Core服務默認情況下時使用WorkStation GC
工作站模式來回收。
-
Server GC
會擁有更大的內存,Server GC
會為每個處理器創建一個用於執行垃圾回收的堆和專用線程,每個堆都擁有一個小對象堆和大對象堆,並且所有的堆都可以訪問。 不同堆上的對象可以相互引用。因為多個垃圾回收線程一起工作,所以對於相同大小的堆Server GC
垃圾回收比WorkStation GC
垃圾回收更快一些。但是Server GC
回收會佔用大量資源,這種模式的特點是初始分配的內存較大,並且盡可能不回收內存,進行回收用時會很耗時,並進行內存碎片整理工作。 -
Workstation GC
的內存相對於Server GC
就很小啦,且它的回收線程就是服務的線程且有較高的優先級,因為必須與其他線程競爭 CPU 時間來進行回收。
不同模式下的內存分配
GC的回收模式
GC
有三種回收模式
-
Non-Concurrent GC
非并行回收模式:在非并行模式下,回收時候會掛起所有其他的線程影響服務的性能。 -
Concurrent GC
并行回收模式: 并行會後可以解決非并行回收引起的線程掛起,讓其他線程和回收線程一起運行,使服務可以更快的響應,并行回收只會發生在Generation 2
中,Generation 0/1
始終都是非併發的,因為他們都是小對象回收的速度很快。在并行回收的時候我們依舊可以分配對象到Generation 0/1
中。 -
Background GC
後台回收模式:Background GC
是Concurrent GC
的增強版本。 區別在Background GC
回收Generation 2
的時允許了Generation 0/1
進行清理。在WorkStation GC
下會使用一個專用的後台垃圾回收線程,而Server GC
下會使用多個線程來進行回收。且Server GC
下回收線程不會超時。
非并行回收:
并行回收
WorkStation GC 後台回收
Server GC 後台回收
GC回收類型配置
推薦使用runtimeconfig.json
文件和環境變量COMPlus_gcServer
來配置。
COMPlus_gcServer
0 = WorkStation GC
COMPlus_gcServer
1 = Server GC
{
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
//true - Server GC false - WorkStation GC
}
}
}
GC回收模式配置
推薦使用runtimeconfig.json
文件和環境變量COMPlus_gcConcurrent
來配置。
COMPlus_gcConcurrent
0 =Non-Concurrent GC
COMPlus_gcConcurrent
1 =Background GC
{
"runtimeOptions": {
"configProperties": {
"System.GC.Concurrent": true
//true- Background GC false -Non-Concurrent GC
}
}
}
強制回收
在一些特殊的情況下強制回收是可以提高服務的性能的,可以向GC.Collect()
提供GCCollectionMode
枚舉值觸發強制回收。
- Default :默認的回收設置。
- Forced :立即強制進行垃圾回收。
- Optimized :
GC
來判斷時間是否是回收對象的最佳時間,如GC
判定回收效率不高因此回收不合理的情況下將返回不回收對象。
GC.Collect( (int) GCCollectionMode.Forced);
延遲回收
在我們的服務在檢索數據或者處理邏輯的時候可能會發生垃圾回收,從而妨礙性能,可以通過System.Runtime.GCLatencyMode
來配置延遲回收
-
GCLatencyMode.LowLatency:禁止
Generation 2
回收,只回收Generation 0/1
,這個只能在短時間內使用,如果長時間使用內存處於壓力下GC
還是會觸發回收,這個配置只對WorkStation GC
可用。 -
GCLatencyMode.SustainedLowLatency :禁止
Generation 2
的Foreground GC
(前台回收),只回收Generation 0/1
和Generation 2
後台回收。WorkStation GC
和Server GC
都可以使用,且可以長時間使用,但是如果禁用Background GC
,將無法使用。
GC.Collect( (int) GCLatencyMode.SustainedLowLatency);
參考文章
從ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection
微軟文檔
總結
參考了一些大佬和官方的文檔簡單的去了解了一下GC的工作原理,方便在開發中有效區分配使用內存資源,文中如有錯誤大佬們可以在評論區指出。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※超省錢租車方案
※別再煩惱如何寫文案,掌握八大原則!
※回頭車貨運收費標準
※教你寫出一流的銷售文案?