.NET Core中GC的工作原理
轉自:她微笑的臉 cnblogs.com/linhuiy/p/13183140.html
前言
.NET中GC管理你服務的內存分配和釋放,GC是運行公共語言運行時(CLR Common Language Runtime)中,GC可以幫助開發(fā)人員有效的分配內存和和釋放內存,大多數(shù)情況下是不需要去擔心的,但是有時候服務總是是出現(xiàn)莫名的問題,所以還是有必要了解一下GC的基礎知識的。這里就不介紹內存方面的知識了。
GC回收過程
GC將對象分為大對象和小對象,如果對象的大小大于或者等于85000byte將被視為大對象,大對象會被分配到到(LOH) Large Object Heap中去。
GC有一個代數(shù)的概念Generation,分為三代

Generation 0:?0代,這里面都是生命周期很短的對象,比如臨時變量,當你new一個對象的時候該對象都會在Generation 0中,這里的對象將很快的被GC回收,但是當你new的是一個大對象的時候它會直接進去大對象堆(LOH)
Generation 1:?1代,這一代包含的也基本是生命周期很短的對象。它是短期對象和長期對象之間的緩沖區(qū)。
Generation 2:?2代,這一代包含的都是生命周期長的對象,它們都是從1代和2代中選拔出來的,LOH屬于2代。
當分配的對象使用的內存超出了GC的閾值時回收就會開始。閾值是隨著服務的運行GC自己調整的?;蛘咧苯诱{用GC.Collect方法也可以開始回收。
回收開始時GC會開始循環(huán)遍歷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會為每個處理器創(chuàng)建一個用于執(zhí)行垃圾回收的堆和專用線程,每個堆都擁有一個小對象堆和大對象堆,并且所有的堆都可以訪問。不同堆上的對象可以相互引用。因為多個垃圾回收線程一起工作,所以對于相同大小的堆Server GC垃圾回收比WorkStation GC垃圾回收更快一些。但是Server GC回收會占用大量資源,這種模式的特點是初始分配的內存較大,并且盡可能不回收內存,進行回收用時會很耗時,并進行內存碎片整理工作。
Workstation GC的內存相對于Server GC就很小啦,且它的回收線程就是服務的線程且有較高的優(yōu)先級,因為必須與其他線程競爭 CPU 時間來進行回收。
不同模式下的內存分配

GC的回收模式
GC有三種回收模式
Non-Concurrent GC 非并行回收模式:在非并行模式下,回收時候會掛起所有其他的線程影響服務的性能。
Concurrent GC 并行回收模式:并行會后可以解決非并行回收引起的線程掛起,讓其他線程和回收線程一起運行,使服務可以更快的響應,并行回收只會發(fā)生在Generation 2中,Generation 0/1始終都是非并發(fā)的,因為他們都是小對象回收的速度很快。在并行回收的時候我們依舊可以分配對象到Generation 0/1中。
Background GC 后臺回收模式:Background GC 是 Concurrent GC的增強版本。區(qū)別在Background GC回收Generation 2的時允許了Generation 0/1 進行清理。在WorkStation GC下會使用一個專用的后臺垃圾回收線程,而Server GC下會使用多個線程來進行回收。且Server GC下回收線程不會超時。
非并行回收

并行回收

WorkStation GC 后臺回收

Server GC 后臺回收

GC回收類型配置
推薦使用runtimeconfig.json文件和環(huán)境變量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文件和環(huán)境變量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枚舉值觸發(fā)強制回收。
Default :默認的回收設置。
Forced :立即強制進行垃圾回收。
Optimized :GC來判斷時間是否是回收對象的最佳時間,如GC判定回收效率不高因此回收不合理的情況下將返回不回收對象。
GC.Collect( (int) GCCollectionMode.Forced);延遲回收
在我們的服務在檢索數(shù)據(jù)或者處理邏輯的時候可能會發(fā)生垃圾回收,從而妨礙性能,可以通過System.Runtime.GCLatencyMode來配置延遲回收
GCLatencyMode.LowLatency:禁止Generation 2回收,只回收Generation 0/1,這個只能在短時間內使用,如果長時間使用內存處于壓力下GC還是會觸發(fā)回收,這個配置只對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
https://docs.microsoft.com/zh-cn/dotnet/standard/garbage-collection/fundamentals
總結
參考了一些大佬和官方的文檔簡單的去了解了一下GC的工作原理,方便在開發(fā)中有效區(qū)分配使用內存資源,文中如有錯誤大佬們可以在評論區(qū)指出。
