博客 / 詳情

返回

go-GC

併發三色標記法

三色:黑、灰、白

  • 黑對象代表,對象自身存活,且其指向對象都已標記完成
  • 灰對象代表,對象自身存活,但其指向對象還未標記完成
  • 白對象代表,對象尙未被標記到,可能是垃圾對象

標記過程:

  1. 初始化:所有對象都被標記為白色
  2. 將根對象(全局對象、棧上局部變量等)置黑,將其所指向的對象置灰
  3. 從灰對象出發,將其所指向的對象都置灰. 所有指向對象都置灰後,當前灰對象置黑
  4. 標記結束後,白色對象就是不可達的垃圾對象,需要進行清掃

可能產生的問題

  1. 漏標 ->屏障機制

在某個對象標記為黑色之後,它新指向了一個對象,可能該對象之前被某灰色對象標記,還未掃描到,灰色對象就刪除了對該對象的指向

  1. 多標 ->下一輪GC

在標記完一個灰色對象時,刪除了指向它的黑色對象對它的引用

屏障機制

強弱三色不變式

  • 強三色不變式:白色對象不能被黑色對象直接引用
  • 弱三色不變式:白色對象可以被黑色對象引用,但要從某個灰對象出發仍然可達該白對象

插入寫屏障

屏障機制類似於一個回調保護機制,指的是在完成某個特定動作前,會先完成屏障成設置的內容,插入寫屏障(Dijkstra)的目標是實現強三色不變式,當一個對象引用另一個對象時,將被引用的對象標記為灰色。

刪除寫屏障

刪除寫屏障(Yuasa barrier)的目標是實現弱三色不變式,保證當一個白色對象即將被上游刪除引用前,會觸發屏障將其置灰,之後再刪除上游指向其的引用。

混合寫屏障

通過結合這兩種寫屏障技術,Go 的垃圾回收器可以在併發標記階段運行,而無需停止整個程序(Stop-the-World)。

插入寫屏障和刪除寫屏障的短板:

  • 插入寫屏障:結束時需要STW來重新掃描棧,標記棧上引用的白色對象的存活;
  • 刪除寫屏障:回收精度低,GC開始時STW掃描堆棧來記錄初始快照,這個過程會保護開始時刻的所有存活對象。

混合寫屏障操作:

  • GC 開始前,以棧為單位分批掃描,將棧中所有對象置黑
  • GC 期間,棧上新創建對象直接置黑
  • 堆對象正常啓用插入寫屏障(添加的對象置為灰色)
  • 堆對象正常啓用刪除寫屏障(被刪除引用的對象被標記為灰色)
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.