筆記首發(fā)于:lengyueling.cn
什么是CLR
-
公共語言運行庫 (common language runtime,CLR) 是托管代碼執(zhí)行核心中的引擎。
-
運行庫為托管代碼提供各種服務,如跨語言集成、代碼訪問安全性、對象生存期管理、調試和分析支持。
-
它是整個.NET框架的核心,它為.NET應用程序提供了一個托管的代碼執(zhí)行環(huán)境。
-
它實際上是駐留在內存里的一段代理代碼,負責應用程序在整個執(zhí)行期間的代碼管理工作。
-
它的其中一個重要作用就是進行.NET平臺下語言的垃圾回收
GC垃圾回收
什么是垃圾回收
-
Net程序可以找出某個時間點上哪些已分配的內存空間沒有被程序使用,并自動釋放它們。
-
自動找出并釋放不再使用的內存空間的機制,就稱為垃圾回收機制(Garbage Collection,簡稱GC)。
-
.NET CLR使用分代收集算法+標記壓縮算法來進行GC。
垃圾回收的對象
-
對于堆中內存,通過識別它們是否被引用來確定哪些對象是垃圾,哪些對象仍要被使用,垃圾就是沒有被任何變量、對象引用的內容。
-
GC只負責堆內存的垃圾回收,引用類型都是存在堆中的,所以他的分配和釋放都需要垃圾回收機制來管理。
-
棧上的內存是通過系統(tǒng)自動管理的,值類型在棧中分配內存,他們有自己的生命周期,不需要主動對他們進行管理,系統(tǒng)會自動分配和釋放。
垃圾回收的主要作用
-
分配對象(比如說實例化對象的時候負責分配內存給對象)
-
垃圾回收(比如回收我們寫C#代碼時產生的垃圾)
分配對象
-
分為大對象和小對象分配
-
超過85000字節(jié)(83k)的為大對象,否則為小對象
-
大對象會被存放在第二代內存中,目的是減少性能損耗,提高性能
-
-
分配小對象在短暫堆或者由自由對象列表進行分配,分配大對象直接在大對象堆段中
-
一個區(qū)域->多個堆(普通堆和短暫堆)
-
區(qū)域是CLR初始化的時候內存里開辟的一段空間
-
-
在CLR中分為3個代:0代(存放短暫堆,存放小對象),1代(存放短暫堆,存放小對象),2代(存放普通堆,同時存放大對象和小對象)
-
代是GC機制中使用的一種算法(分代算法),每次分配都有可能GC以釋放內存(某一代存不下時,或者后面說的各種觸發(fā)GC的條件成立時)
-
-
如果我們有一個堆可以放100個字節(jié),一次GC分配后用了90個字節(jié),剩余的字節(jié)就是自由對象,如果有多個堆形成的多個自由對象就是自由對象列表
-
垃圾回收
觸發(fā)GC的條件
-
分配對象找不到可用空間(代空間不足)
-
分配量超過閾值(CLR初始化時的一個閾值上下限)
-
收到Windows報告物理內存不足的通知
-
直接調用GC.Collect()手動觸發(fā)(unity可以在loading的時候觸發(fā))
-
CLR卸載AppDomain
-
CLR正在關閉
GC垃圾回收的步驟
-
1.停止其他線程,切換其他線程到搶占模式
-
合作模式:在CLR里面運行的線程,可以無限制的訪問托管堆和非托管堆
-
搶占模式:只能訪問非托管堆,托管堆不能訪問
-
之所以有這步是因為gc的時候如果不進入搶占模式,可能會造成訪問到被回收的對象而發(fā)生錯誤
-
-
2.重新判定傳入的GC回收目標的代是否合適,主要判斷條件有:
-
碎片空間率
-
短暫堆剩余空間
-
卡片掃描效率
-
物理內存占用率
-
是否執(zhí)行后臺GC
-
-
3.判斷是否執(zhí)行后臺GC
-
執(zhí)行后臺GC,進行標記和清掃
-
不執(zhí)行后臺GC,則執(zhí)行普通GC,進行標記、計劃、重定位、壓縮、清掃等操作
-
-
簡略版本(標記壓縮算法):
-
如果0代內存滿了,gc首先會認為堆中全是垃圾,然后進行下面兩步
-
標記對象:從根(靜態(tài)對象、方法參數)開始檢查被引用的對象,將其標記為可達對象,其他為不可達對象
-
搬遷對象壓縮堆,釋放不可達對象,搬遷可達對象到1代,修改引用地址
-
如果1代內存滿了,重復上面步驟,將0代可達對象搬遷到1代,1代可達對象搬遷到2代堆,以此類推。
-
垃圾回收算法
標記清除(Mark Sweep)
-
簡單描述:
-
是最基礎的GC算法。
-
分為標記階段和清除階段。
-
標記階段遍歷堆(根的直接引用,然后遞歸)為所有的活動對象打上標記。
-
清除階段(從堆的開始到結束遍歷每一個對象)如果是已經標記的,設置為未標記,未標記的連接到空閑鏈表(用作以后的分配),如果有連續(xù)的分塊則合并。
-
-
如何分配:遍歷空閑鏈表根據策略選擇合適的對象,下面是三種策略。
-
First - fit(遇到大于等于的分塊就直接返回)
-
Best - fit(返回大于等于的最小分塊)
-
Worst - fit(返回最大的分塊)
-
-
優(yōu)點:
-
簡單
-
與保守式GC 算法兼容(也就是不移動對象)
-
-
缺點:
-
碎片化(也就是空閑鏈表中存在,一堆不連續(xù)的小分塊,不論采用那種分配策略都無法避免碎片化)
-
分配速度慢(每次分配都需要遍歷空閑鏈表,舉個極端的,每次合適的都是最后一個)
-
與寫時復制技術不兼容(寫時復制技術(眾多UNIX 操作系統(tǒng)的虛擬存儲中用到的高速化方法。)
-
復制進程的時候大部分內存不會被復制而是共享,共享內存不能直接重寫,想要重寫得復制到自己的私有空間,不訪問共享內存
-
引用計數(Reference Counting)
-
簡單描述:
-
每個對象有個計數器,在每次指針更新時,新指向的對象的計數器++
-
之前指向的對象的計數器--
-
如果等于0回收,加入空閑鏈表。
-
-
如何分配:遍歷空閑鏈表
-
優(yōu)點:
-
可即可回收垃圾(當計數器為0時直接回收)
-
最大暫停時間短(每次指針更新時都會回收垃圾)
-
沒有必要沿指針查找(上面的標記清楚算法,需要由根開始查找)
-
-
缺點:
-
計數器值的增減處理繁重
-
計數器要占用很多位
-
實現繁瑣復雜
-
循環(huán)引用無法回收(比如根引用A ,A和B兩個互相引用,當根不引用A的時候 A和B已經是垃圾了,但是互相引用計數器都是1,無法回收)
-
復制集合(Copy Collection)
-
簡單描述:
-
把堆平分為From,To兩個空間,如果現在活動對象,垃圾是在From空間,從根開始遞歸(深度遍歷),把所有的對象復制到To空間,反之亦然。
-
如何分配:當前活躍的空間,未分配的部分,按內存順序分配。
-
-
優(yōu)點:
-
優(yōu)秀的吞吐量(能較短時間完成GC,和標記清楚算法比較,標記清楚需要遍歷兩次,而GC復制遍歷一次+復制)
-
可實現高速分配(直接在未分配的連續(xù)空間分配,不需要遍歷啥的)
-
不會發(fā)生碎片化(每次執(zhí)行GC都把活動對象集中在開頭,放在堆的一端的行為叫做壓縮)
-
與緩存兼容(深度遍歷的復制,有引用關系的對象,在內存中放到了一起)
-
-
缺點:
-
堆使用效率低下(一分為二為兩個空間,只有一半的堆能使用)
-
不兼容保守式GC 算法
-
遞歸調用函數(每次進行復制的時候都要調用函數,遞歸會消耗棧,所以還可能棧溢出)
-
標記壓縮(整理)(Mark Compact)
-
簡單描述:
-
是CLR使用的GC算法。
-
結合標記清除算法和復制算法的優(yōu)點并進行優(yōu)化
-
標記階段遍歷堆(根的直接引用,然后遞歸)為所有的活動對象打上標記
-
整理階段將存活對象移向內存的一段,然后清除邊界外的對象
-
-
優(yōu)點:
-
清除了標記-清除算法當中,內存區(qū)域碎片化的缺點。
-
消除了復制算法當中,內存減半的高額代價。
-
-
缺點
-
從效率上來說,標記-整理算法要低于復制算法。
-
移動對象的同時,如果對象被其它對象引用,則還需要調整引用 的地址。
-
移動過程中,需要全程暫停用戶應用程序,即STW。
-
分代收集(Generational Collection)
-
當前商業(yè)虛擬機的垃圾收集都采用“分代收集”(Generational Collection)算法,這種算法并沒有什么新的思想,只是根據對象存活周期的不同將內存劃分為幾塊。
-
一般是把堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。
-
在新生代中,每次垃圾收集時都發(fā)現有大批對象死去,只有少量存活,那就選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。
-
而老年代中因為對象存活率高、 沒有額外空間對它進行分配擔保,就必須使用“標記—清理”或者“標記—整理”算法來進行回收。
資料參考、拓展閱讀
Unity優(yōu)化之GC分配問題_嗶哩嗶哩_bilibili(Unity優(yōu)化之GC分配問題)
.Net CLR視頻2021年最新講解CLR核心機制,CLR模型,性能優(yōu)化原理。_嗶哩嗶哩_bilibili(.Net CLR視頻2021年最新講解CLR核心機制,CLR模型,性能優(yōu)化原理)
第9課:構造、析構、垃圾回收_嗶哩嗶哩_bilibili(【唐老獅】Unity系列之C#四部曲—C#核心-垃圾回收)
.NET:GC_丿灬鑫崽丶的博客-CSDN博客_.net core 析構函數(.NET:GC)
垃圾回收的算法與實現(一)三類基本算法_璃殤Yiyi的博客-CSDN博客(垃圾回收的算法與實現(一)三類基本算法)
CLR的GC_璃殤Yiyi的博客-CSDN博客(CLR的GC)
unity GC機制簡單介紹_ZEKEGU1997的博客-CSDN博客_unity的gc(unity GC機制簡單介紹)
Unity優(yōu)化之GC——合理優(yōu)化Unity的GC - zblade - 博客園(Unity優(yōu)化之GC——合理優(yōu)化Unity的GC)
C#——垃圾回收(GC)_面向大象編程的博客-CSDN博客_c# 垃圾回收(C#——垃圾回收(GC))
lua的GC原理_LJY_rookie的博客-CSDN博客(lua的GC原理)
.NET垃圾回收(GC)原理 - awp110 - 博客園(.NET垃圾回收(GC)原理)
四種垃圾回收算法(標記-清除算法【Mark-Sweep】,復制算法【Coping】,標記-整理算法【Mark-Compact】,分代收集算法【Generational Collection】) - ~晶晶~ - 博客園(四種垃圾回收算法)
標記整理算法(Mark-Compact)_永遠的HelloWorld的博客-CSDN博客(標記整理算法(Mark-Compact))
http://t.csdn.cn/BOZ6m(標記-壓縮(整理)算法)
淺析CLR的GC(垃圾回收器) - 3WLineCode - 博客園(淺析CLR的GC(垃圾回收器))
公共語言運行庫_百度百科(公共語言運行庫CLR)文章來源:http://www.zghlxwxcb.cn/news/detail-514259.html
托管代碼和非托管代碼_qq_38234381的博客-CSDN博客_托管代碼和非托管代碼(托管代碼和非托管代碼)文章來源地址http://www.zghlxwxcb.cn/news/detail-514259.html
到了這里,關于.NET CLR之垃圾回收(GC)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!