golang v1.3前-標(biāo)記清除(mark and sweep)方法
標(biāo)記清除再gc前會進(jìn)行STW,STW - MARK標(biāo)記 - SWEEP清除 - 停止STW
1、STW暫停程序業(yè)務(wù)邏輯孩饼,找出不可達(dá)對象和可達(dá)對象髓削;
2、開始標(biāo)記镀娶,程序找出所有的可達(dá)對象做上標(biāo)記立膛;
3、標(biāo)記完之后梯码,開始清楚未標(biāo)記對象宝泵;
4、停止暫停轩娶,讓程序繼續(xù)運(yùn)行鲁猩。循環(huán)重復(fù)這個過程,直到程序生命周期結(jié)束罢坝;
不足:
1廓握、STW程序暫停,程序出現(xiàn)卡頓(嚴(yán)重問題)
2嘁酿、標(biāo)記需要掃描整個heap
3隙券、清除數(shù)據(jù)會產(chǎn)生heap碎片
4、緩解辦法:可將三步和四步換位置闹司,縮短STW位置娱仔,但仍然不能解決根本問題
golang v1.5三色標(biāo)記法
go引入白色、灰色游桩、黑色標(biāo)記表
1牲迫、只要創(chuàng)建新的對象默認(rèn)顏色都標(biāo)記為白色,保存到程序中根集合(root set)
2借卧、每次gc回收開始盹憎,從跟節(jié)點開始遍歷所有對象,把遍歷到的對象從白色集合放到灰色集合
3铐刘、遍歷灰色節(jié)點陪每,將灰色對象引用的對象從白色集合放到灰色集合,之后將此灰色集合放到黑色集合
4镰吵、重復(fù)第三步檩禾,直到灰色中無任何對象
5、刪除白色標(biāo)標(biāo)記的對象疤祭,也就是gc
缺點:
下面是三色標(biāo)記法最不希望發(fā)生的事情
條件1:一個白色對象被黑色對象引用盼产、白色對象被掛在黑色對象下
條件2:灰色對象與它之間的可達(dá)關(guān)系的白色對象遭到破壞
兩個條件同時滿足時,就會出現(xiàn)對象丟失的現(xiàn)象
解決:最簡單的方式就是STW
STW的過程有明顯的資源浪費(fèi)勺馆,對所有的用戶程序都有很大影響
如何能在保證對象不丟失的情況盡可能的提高GC效率戏售,減少STW的時間呢啦辐?不能添加STW,添加就和標(biāo)記清楚沒區(qū)別了
強(qiáng)弱三色不變式:
不使用STW蜈项,破壞上述兩個條件:
強(qiáng)三色不允許黑色對象引用白色對象,只允許引用灰色對象(破壞條件1)
弱三色黑色對象可以引用白色對象续挟,白色對象存在其他灰色對象對它的引用紧卒,或者可達(dá)它的鏈路上游存在灰色對象(破壞條件2)
寫屏障機(jī)制:在gc過程中加入機(jī)制插入與刪除機(jī)制
插入屏障:對象被引用時觸發(fā)的機(jī)制
具體操作:A對象引用B對象的時候,B必須標(biāo)記為灰色(B掛在A的下游诗祸,B必須唄標(biāo)記為灰色)
滿足:強(qiáng)三色不變式(不存在黑色對象引用白色對象的情況了跑芳,因為白色的會強(qiáng)制變成灰色)
為了保證效率,不在棧上設(shè)置插入屏障直颅,堆上啟用插入屏障
不足:結(jié)束是需要STW來掃描棧博个,時間大約為10~100ms
刪除屏障:對象被刪除時觸發(fā)的機(jī)制
具體操作:被刪除的對象,如果自身為灰色或者白色功偿,那么被標(biāo)記為灰色
滿足:若三色不變式(保護(hù)灰色對象到白色對象的路徑不會斷)
不足:回收精度低盆佣,一個對象即時被刪除了最后一個指向它的指針也依舊可以活過這一輪,在下一輪GC中被清除
golang v1.8的三色標(biāo)記法+混合寫屏障機(jī)制
1械荷、GC開始將棧上的對象全部掃描并標(biāo)記為黑色(之后不再進(jìn)行第二次重復(fù)掃描共耍,無需STW)
2、GC期間吨瞎,任何在棧上創(chuàng)建的對象痹兜、均為黑色
3、被刪除的對象標(biāo)記為灰色
4颤诀、被添加的對象標(biāo)記為灰色