1. 程式人生 > 其它 >【golang】GC垃圾回收機制設計原理

【golang】GC垃圾回收機制設計原理

GC垃圾回收機制設計原理

標記清除

1.3版本之前。大概分為兩階段:

標記階段 - 從根物件出發標記堆中存活的物件

清除階段 - 遍歷堆中所有物件,回收未被標記的垃圾物件

1.0版本:是完全序列的,這兩個階段都在STW暫停範圍之內

1.1版本:在多核主機並行執行垃圾收集的標記和清除階段

缺點:整個過程都需要 STW

三色標記

概述:

三色只是為了敘述上方便抽象出來的一種說法,實際上物件並沒有顏色之分。這裡的三色,對應了垃圾回收過程中物件的三種狀態:

白色是要回收的,黑色是被引用的,灰色是物件還在標記佇列中等待。當標記階段結束之後,只有黑色存活物件和白色垃圾物件

1.5版本 實現了基於三色標記清掃和寫屏障技術的併發

垃圾收集器

垃圾收集器執行過程:

  1. 在垃圾收集器開始工作時,程式中不存在任何的黑色物件,垃圾收集的根物件會被標記成灰色。
  2. 垃圾收集器只會從灰色物件集合中取出物件開始掃描,從灰色物件的集合中選擇一個灰色物件並將其標記成黑色,將該黑色物件指向的所有物件都標記成灰色,保證該物件和被該物件引用的物件都不會被回收。
  3. 重複上一步驟,當不存在灰色物件時,標記階段就會結束。

缺點:三色標記清除演算法本身是不可以併發或者增量執行的,它仍然需要 STW。

如果沒有STW,在併發執行時,當以下兩個條件同時被滿足就會有物件丟失

  • 條件一:灰色物件失去了一個白色物件
  • 條件二:同時這個白色物件被黑色物件引用

因為是以上兩個條件同時滿足才會有物件丟失,所以只要破壞其中一個條件就行,對應兩種方法:

強三色不變式:破壞條件二,強制性不允許黑色物件引用白色物件

弱三色不變式:破壞條件一,當白色物件存在其他灰色物件對它的引用,或者鏈路上游存在灰色物件,那麼黑色物件才能引用該白色物件。如圖:

黑色物件可以引用該白色物件

黑色物件不能引用該白色物件

屏障機制

屏障技術就是在併發或者增量標記過程中保證三色不變性的重要技術。

這裡想要介紹的是 Go 語言中使用的兩種寫屏障技術:插入寫屏障刪除寫屏障

插入寫屏障

物件被引用時觸發的機制

具體操作:在A物件引用B物件的時候,B物件被標記為灰色,滿足了強三色不定式

注意:因為棧上的物件在垃圾收集中也會被認為是根物件,在棧上使用插入寫屏障會大幅度增加寫入指標的額外開銷,影響效能。所以 Go 團隊在實現上選擇在棧上不觸發插入寫屏障,而是在標記完成後,暫停服務(STW),將棧上所有物件設為白色物件,重新從根物件遍歷掃描,之後再回收白色垃圾物件

不足:結束時需要STW來重新掃描棧,大約需要10~100ms

刪除寫屏障

物件被刪除時觸發的機制

具體操作:當一個老物件的引用被刪除時,如果該老物件是白色的,將其變為灰色。保證了弱三色不變性。老物件引用的下游物件一定可以被灰色物件引用。

如下圖:

此時B物件刪除C物件的引用,觸發刪除寫屏障機制

C變成灰色,這樣能保證插入時滿足強三色不定式和弱三色不定式,如圖

不足: 回收精度低,一個物件的引用即使被刪除了依然可以活過這一輪,在下一輪GC中被清理掉

混合寫屏障

1.8版本 三色標記法+混合寫屏障將垃圾收集的時間縮短至 0.5ms 以內,整體幾乎不需要STW,效率高

具體操作:

  1. GC開始,優先掃描棧,將可達物件標記為黑色(之後不再進行第二次重複掃描,無需STW)

    注意這裡不是棧裡所有的物件,而是從根節點開始掃描,可達的節點

  2. GC期間,任何在棧上建立的新物件,均為黑色

  3. 被刪除的物件標記為灰色

  4. 被新增的物件標記為灰色

下一篇介紹go語言GC實現原理

注意:這裡不是棧裡所有的物件,而是從根節點開始掃描,可達的節點

  1. GC期間,任何在棧上建立的新物件,均為黑色

  2. 被刪除的物件標記為灰色

  3. 被新增的物件標記為灰色

下一篇介紹go語言GC實現原理