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

Generation 0:?0代,這里面都是生命周期很短的對(duì)象,比如臨時(shí)變量,當(dāng)你new一個(gè)對(duì)象的時(shí)候該對(duì)象都會(huì)在Generation 0中,這里的對(duì)象將很快的被GC回收,但是當(dāng)你new的是一個(gè)大對(duì)象的時(shí)候它會(huì)直接進(jìn)去大對(duì)象堆(LOH)
Generation 1:?1代,這一代包含的也基本是生命周期很短的對(duì)象。它是短期對(duì)象和長(zhǎng)期對(duì)象之間的緩沖區(qū)。
Generation 2:?2代,這一代包含的都是生命周期長(zhǎng)的對(duì)象,它們都是從1代和2代中選拔出來的,LOH屬于2代。
當(dāng)分配的對(duì)象使用的內(nèi)存超出了GC的閾值時(shí)回收就會(huì)開始。閾值是隨著服務(wù)的運(yùn)行GC自己調(diào)整的?;蛘咧苯诱{(diào)用GC.Collect方法也可以開始回收。
回收開始時(shí)GC會(huì)開始循環(huán)遍歷Generation 0中的所有對(duì)象并標(biāo)記所有對(duì)象是活動(dòng)對(duì)象還是非活動(dòng)對(duì)象,標(biāo)記完成后會(huì)更新活動(dòng)對(duì)象的引用。最后會(huì)回收非活動(dòng)對(duì)象占用的內(nèi)存,并把活動(dòng)對(duì)象壓縮后移動(dòng)到Generation 1中,Generation 1中的或?qū)ο笤谝苿?dòng)到Generation 2是默認(rèn)不會(huì)被壓縮的,因?yàn)閺?fù)制大的對(duì)象會(huì)導(dǎo)致性能的下降??梢酝ㄟ^GCSettings.LargeObjectHeapCompactionMode來配置壓縮LOH。
GC的回收類型
GC 回收有兩種類型,WorkStation GC(工作站)和Server GC(服務(wù)器),.Net Core服務(wù)默認(rèn)情況下時(shí)使用WorkStation GC工作站模式來回收。
Server GC會(huì)擁有更大的內(nèi)存,Server GC會(huì)為每個(gè)處理器創(chuàng)建一個(gè)用于執(zhí)行垃圾回收的堆和專用線程,每個(gè)堆都擁有一個(gè)小對(duì)象堆和大對(duì)象堆,并且所有的堆都可以訪問。不同堆上的對(duì)象可以相互引用。因?yàn)槎鄠€(gè)垃圾回收線程一起工作,所以對(duì)于相同大小的堆Server GC垃圾回收比WorkStation GC垃圾回收更快一些。但是Server GC回收會(huì)占用大量資源,這種模式的特點(diǎn)是初始分配的內(nèi)存較大,并且盡可能不回收內(nèi)存,進(jìn)行回收用時(shí)會(huì)很耗時(shí),并進(jìn)行內(nèi)存碎片整理工作。
Workstation GC的內(nèi)存相對(duì)于Server GC就很小啦,且它的回收線程就是服務(wù)的線程且有較高的優(yōu)先級(jí),因?yàn)楸仨毰c其他線程競(jìng)爭(zhēng) CPU 時(shí)間來進(jìn)行回收。
不同模式下的內(nèi)存分配

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

并行回收

WorkStation GC 后臺(tái)回收

Server GC 后臺(tái)回收

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
}
}
}強(qiáng)制回收
在一些特殊的情況下強(qiáng)制回收是可以提高服務(wù)的性能的,可以向GC.Collect()提供GCCollectionMode枚舉值觸發(fā)強(qiáng)制回收。
Default :默認(rèn)的回收設(shè)置。
Forced :立即強(qiáng)制進(jìn)行垃圾回收。
Optimized :GC來判斷時(shí)間是否是回收對(duì)象的最佳時(shí)間,如GC判定回收效率不高因此回收不合理的情況下將返回不回收對(duì)象。
GC.Collect( (int) GCCollectionMode.Forced);延遲回收
在我們的服務(wù)在檢索數(shù)據(jù)或者處理邏輯的時(shí)候可能會(huì)發(fā)生垃圾回收,從而妨礙性能,可以通過System.Runtime.GCLatencyMode來配置延遲回收
GCLatencyMode.LowLatency:禁止Generation 2回收,只回收Generation 0/1,這個(gè)只能在短時(shí)間內(nèi)使用,如果長(zhǎng)時(shí)間使用內(nèi)存處于壓力下GC還是會(huì)觸發(fā)回收,這個(gè)配置只對(duì)WorkStation GC可用。
GCLatencyMode.SustainedLowLatency :禁止Generation 2的 Foreground GC (前臺(tái)回收),只回收Generation 0/1和Generation 2后臺(tái)回收。WorkStation GC和Server GC都可以使用,且可以長(zhǎng)時(shí)間使用,但是如果禁用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
總結(jié)
參考了一些大佬和官方的文檔簡(jiǎn)單的去了解了一下GC的工作原理,方便在開發(fā)中有效區(qū)分配使用內(nèi)存資源,文中如有錯(cuò)誤大佬們可以在評(píng)論區(qū)指出。
