Go语言垃圾回收(GC)
1. Go V1.3之前的標記清除(mark and sweep)
1. 1 標記清除法的基本流程
第一步 : STW(stop the world)暫停所有的程序業務邏輯, 找出可達對象和不可達對象(程序調用對象)
第二步 : 開始標記, 程序找出他所有的可達對象并進行標記
第三步 : 清除所有不可達對象, 就是未標記的對象
第四步 : 停止暫停, 讓程序繼續跑, 然后重復這個過程, 直到程序結束
1. 2 標記清除的缺點
- STW, 會讓程序變慢
- 標機過程需要將全部的堆棧進行一遍掃描來確定是不是可達對象
- 刪除的過程中, 會產生heap碎片
2. Go V 1.5 三色標記法
2. 1三色標記法的基本流程
三種顏色 白色, 灰色, 黑色. 總圖在這
2. 2 如果沒有STW保護的三色標記法會出什么問題呢 ?
假如沒有STW的保護, 那么我們在標記和程序運行的過程中, 其實這兩個過程是并行發生的.
那么會不會發生如下情況
那么當我們遍歷到對象2時, 對象3就無法被標記為灰色對象了. 因為我們是不會再去遍歷黑色的對象. 那么此時對象3就會被誤當為垃圾對象給處理了
所以這是golang中三色標記法最不愿意看到的一幕
如果上述兩個條件都滿足了, 那么很有可能發生對象丟失!!!
那么該如何解決呢 ?
其實最簡單的方法就是加STW
但是STW對于程序有很大的資源浪費.
那么如何保證有效執行GC期間又減少STW的時間來加快效率呢
我們首先介紹一下強弱三色不變式, 再來介紹如何解決這個問題
2. 3 強弱三色不變式
只要解決上述兩個問題, 那么就可以保證對象不被丟失.
所以Google提出了兩種方法
只要讓上面兩個條件不滿足一個即可
一個白色的條件不允許掛在黑色條件下
黑色條件下可以掛白色條件但是白色條件要能被找到 (意思就是白色條件要被灰色條件所指向, 或者是在白色條件的鏈路上游能找到灰色條件)
3. 屏障法(用來滿足強弱三色不變式)
3. 1 插入屏障
具體操作: 在A對象引用B對象的時候,B對象被標記為灰色。(將B掛在A下游,B必須被標記為灰色)
滿足: 強三色不變式. (不存在黑色對象引用白色對象的情況了, 因為白色會強制變成灰色)
我們知道,黑色對象的內存槽有兩種位置, 棧和堆.
棧空間的特點是容量小,但是要求相應速度快,因為函數調用彈出頻繁使用, 所以“插入屏障”機制,在棧空間的對象操作中不使用. 而僅僅使用在堆空間對象的操作中使用.
? 接下來,我們用幾張圖,來模擬整個一個詳細的過程, 希望您能夠更可觀的看清晰整體流程。
插入屏障的缺點
還是需要STW的加入, 對程序資源消耗大, 但是相對于之前的全局STW, 那又小了很多
3. 2 刪除屏障
具體操作: 開始時, 利用快照的方式, 需要進行STW, 然后被刪除的對象,如果自身為灰色或者白色,那么被標記為灰色。
滿足: 弱三色不變式. (保護灰色對象到白色對象的路徑不會斷)
刪除屏障的缺點
如上圖所示, 對象1刪除了對于對象5的引用, 所以對象5被標記為了灰色, 最后的又被標記為了黑色, 那么他不是沒有被刪除了嗎 ?
實際上這就是刪除屏障的缺點 :
這種方式的回收精度低,一個對象即使被刪除了最后一個指向它的指針也依舊可以活過這一輪,在下一輪GC中被清理掉。
但是這個對象就是會在下一輪GC中被刪除
4. Go V1.8 混合寫屏障
具體操作:
1、GC開始將棧上的可達對象全部掃描并標記為黑色(之后不再進行第二次重復掃描,無需STW),
2、GC期間,任何在棧上創建的新對象,均為黑色。
3、被刪除的對象標記為灰色。
4、被添加的對象標記為灰色。
滿足: 變形的弱三色不變式.
這里我們注意, 屏障技術是不在棧上應用的,因為要保證棧的運行效率。
混合寫屏障是GC的一種屏障機制,所以只是當程序執行GC的時候,才會觸發這種機制。
? Golang中的混合寫屏障滿足弱三色不變式,結合了刪除寫屏障和插入寫屏障的優點.
只需要在開始時并發掃描各個goroutine的棧,使其變黑并一直保持,這個過程不需要STW.
而標記結束后,因為棧在掃描后始終是黑色的,也無需再進行re-scan操作了,減少了STW的時間。
5. 總結
GoV1.3- 普通標記清除法,整體過程需要啟動STW,效率極低。
GoV1.5- 三色標記法, 堆空間啟動寫屏障,棧空間不啟動,全部掃描之后,需要重新掃描一次棧(需要STW),效率普通
GoV1.8-三色標記法,混合寫屏障機制, 棧空間不啟動,堆空間啟動。整個過程幾乎不需要STW,效率較高。
6. 現代GC流程
標記之前和標記完成之后需要進行短暫的STW. 來開啟和終止寫屏障
總結
以上是生活随笔為你收集整理的Go语言垃圾回收(GC)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Go语言线程与协程之间的关系之GMP模型
- 下一篇: Mysql事务转载好文