.NET CLR GC的知識點彙總

  • GC的處理流程算法

    • GC暫停進程中的全部線程。
    • GC遍歷堆中的全部對象,將某個位(這個位包含在對象同步塊索引的字段中)設置爲0(0表示將被刪除)。
    • GC檢查全部活動根(根是指引用類型的變量),把活動根指向的對象標記爲1,再次該對象引用的其它對象標記爲1,依次類推。
    • GC將活動對象進行從新排列,讓全部倖存對象在內存中緊挨在一塊兒。
    • 將移動過的倖存對象的根更新固定的偏移量。
    • GC恢復進程中的全部線程。
  • GC對活動對象(活動根)的認定:性能

    • 被任何靜態對象或靜態字段引用。
    • 應用程序棧中引用類型的變量指向的對象。
      • 應用程序中的本地引用類型變量。
      • 應用程序方法中的引用類型參數。
    • 等待被終結(finalized)的對象。
  • GC將活動對象進行從新排列後得到的好處:線程

    • 減小活動對象的內存地址範圍,提高訪問活動對象的性能。
    • 讓剩餘的內存空間變成連續的,便於後續分配給新對象。
    • 解決原生堆(非託管堆)的內存碎片問題。
  • GC代的算法的出發點:code

    • 對象越新,生存期越短。
    • 對象越老,生存期越長。
    • 回收堆的一部分,速度快於回收整個堆。
  • GC關於代的算法流程:對象

    • 初始化堆,接下來分配的全部對象都是0代。
    • 某個時間點0代超過預算,觸發一次GC回收。
    • 倖存下來的對象從0代提高到1代,此時0代不包含任何對象。
    • 對1代對象進行緊湊排列。
    • 在0代爲新對象分配內存。
    • 一段時間後再次觸發GC對0代進行回收。
    • 0代回收結束後發現0代的剩餘空間不夠用,此時會觸發對1代的內存進行GC操做。
    • 1代中倖存下來的對象會被提高到2代。
    • 對1代對象進行緊湊排列。
    • 某個時間後再次觸發GC對0代和1代進行回收。
    • 回收結束後發現0代的剩餘空間不夠用,此時會觸發對2代的內存進行GC操做。
    • 對1代和2代對象進行緊湊排列。
    • 某個時間後GC對0-2代回收完成後,發現1代和2代的剩餘空間太多,此時會對0-2代的內存進行從新分配。
  • GC觸發的時機:索引

    • 0代超過預算時。
    • 顯式調用System.GC.Collect()
    • Windows報告低內存
    • AppDomain正在被卸載
    • CLR正常關閉時
  • GC與Finalize(終結)方法進程

    • Finalize方法用於釋放非託管資源的場景。
    • 定義過Finalize方法的對象在分配內存時,會被附加到支持終結的對象列表中。
    • GC在標記對象爲可刪除時會檢查支持終結的對象列表是否存在,若是存在則會移到待終結的對象列表中。
    • 待終結的對象以及它引用的對象在判斷爲待刪除時,這些對象仍是會被臨時性地提高一個代,讓這些對象存活一會來確保終結操做能正常執行。
    • GC利用一個高優先級的線程來檢查待終結的對象列表並調用對象的Finalize方法,Finalize方法完成後將對象引用從該列表中刪除。
    • 下一輪GC觸發時剛被終結的對象以及它引用的對象會被正常回收。
  • GC與大對象內存

    • ≥85,000KB的對象爲大對象。
    • 大對象被分配在獨立的堆地址空間中。
    • 大對象老是2代,而且只在2代回收操做時觸發回收。
    • 大對象通常不會作緊湊操做。
  • 參考資料:
    • 《CLR via C# Fourth Edition》    Jeffrey Richter
    • Fundamentals of garbage collection
      https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
    • C# Garbage Collection Active Rootshttps://stackoverflow.com/questions/8345075/c-sharp-garbage-collection-active-roots
相關文章
相關標籤/搜索