1. 程式人生 > >golang的垃圾回收(GC)機制

golang的垃圾回收(GC)機制

然後再到這裡

golang的垃圾回收採用的是標記-清理(Mark-and-Sweep演算法

就是先標記出需要回收的記憶體物件快,然後在清理掉;

在這裡不介紹標記和清理的具體策略(可以參考https://lengzzz.com/note/gc-in-golang),只介紹 GC過程是怎麼排程的以及stw相關

這個演算法,會導致 stw (stop the world)的問題,中斷使用者邏輯

觸發GC機制

1.    在申記憶體的候,檢查當前當前已分配的記憶體是否大於上次GC後的記憶體的2倍,若是(主GC執行緒為當前M

2.    監控執行緒發現上次GC時間兩分了,觸;將一個

G放到全域性G佇列中去。(主GC執行緒為執行這個GM

每當觸發的時候,在主GC執行緒中就會走如下的GC流程:

1.    stop the world,等待所有的M休眠;此所有的業務邏輯都停止

2.    標記:分配gc標記任務,喚醒 gcproc M(就是第一步休眠的那些),分個,直到所有的M都做完,才束;並且所有M再次入休眠

3.    清理:有一個獨的goroutine去清理已經標記的記憶體象快

4.    start the worldgcwaiting=0醒所有的M(不會超P個數)

對於上面的三個步驟,分別解釋:

stop the world

1.    設定gcwaiting=1個在每一個G之前會檢查一次個狀,如是,會將當前M休眠;

2.    如果M裡面正在執行一個長時間G,咋呢,道會等待G自己切換嗎這樣可要等10ms啊,不能等!決不能等!所以會主動發標記似於上一篇),當前G中斷,再執行下一個G候,就會走到第1

3.    一直等待所有的M進入休眠,此時所有的業務邏輯程式碼都停

標記:

1.    根據gcproc的個數,分配成gcproc段;gcproc-1M行(當前M也算一個

2.    對於一個M醒前設定它的helpgc標記,喚醒之後這個

M會立判斷標記,如是,開始做分配自己的標記務,如果先做完了,就會從別的M裡面找一些來做

3.    等每一個M都做完,會再次入休眠

清理:

1.    過設置引數,可以以一個goroutine  執行,個功能是在1.3版本之後增加的,這樣就直接到下一步了,清理程不是stw

2.    也可以序列的在主GC執行緒執行;這樣的話則清理程也是stw的,

start the world

1.    設定gcwaiting=0

2.    喚醒PM繼續G(此沒有helpgc標記),業務邏輯程式碼開

綜上:

是基於1.4版本的,GC過程在標記過程是(STW)的

1.5版本里面對GC做了很大的優化;採用三色標記,將標記過程細化成三段,只有前後的兩段是stw的;極大地縮短了gcstw時間