清理終止階段(STW)
暫停程式,所有的處理器在這時會進入安全點
我的了解是這裡stw,等待所有協程都知道要開始打開寫屏障了,不然無法做到統一
如果目前垃圾收集循環是強制觸發的,我們還需要處理還未被清理的記憶體管理單元
标記階段-并發執行
将狀态切換至 <code>_GCmark</code>
開啟寫屏障
并發标記
标記輔助(下面介紹)
在這期間遵守混合寫屏障的機制
标記終止階段 -STW
暫停程式、将狀态切換至 <code>_GCmarktermination</code> 并關閉輔助标記的使用者程式;通知其他goroutine關閉寫屏障,停止寫屏障
清理處理器上的線程緩存
清理階段-并發執行
将狀态切換至 <code>_GCoff</code> 開始清理階段,初始化清理狀态并關閉寫屏障;
恢複使用者程式,這時候新建立的對象會标記為白色
背景并發清理所有的記憶體管理單元
主動觸發
runtime.GC — 使用者程式手動觸發垃圾收集;
被動觸發
預設2min沒有觸發過GC,則觸發一次GC
配置設定記憶體時,若記憶體配置設定達到一定比例則觸發
在GC準備階段,go語言給每個P建立一個mark worker協程(就是标記的協程),把對應的g指針存儲到p中,這些mark worker建立後很快陷入休眠,等到标記階段得到排程執行
GC預設的CPU目标使用率為25%
GC在mark worker中引入了三種不同的工作模式:
<code>gcMarkWorkerFractionalMode</code> -- 當垃圾收集的背景 CPU 使用率達不到預期時(預設為 25%),啟動該類型的工作協程幫助垃圾收集達到使用率的目标,因為它隻占用同一個 CPU 的部分資源,是以可以被排程;
<code>gcMarkWorkerDedicatedMode</code> -- 處理器專門負責标記對象,不會被排程器搶占
<code>gcMarkWorkerIdleMode</code> -- 當處理器沒有可以執行的 Goroutine 時,它會運作垃圾收集的标記任務直到被搶占;
三種不同模式的工作協程會互相協同保證垃圾收集的 CPU 使用率達到期望的門檻值
使用者程式有可能在GC期間配置設定新的記憶體,為了保證使用者程式配置設定記憶體的速度不會超出背景任務的标記速度,運作引入了标記輔助技術。
在目前Go實作中,當GC觸發後,首先進入并發标記階段,并發标記會設定一個标志<code>gcAssistBytes</code> 字段,這個字段存儲了目前協程輔助标記的對象位元組數。在并發标記階段期間,當 Goroutine 配置設定新對象時,會檢查此時 是否處于入不敷出的狀态。
如果是,會暫停配置設定記憶體過快的哪些goroutine,并将其轉去執行一些輔助标記的工作,進而達到放緩繼續配置設定、輔助GC的标記工作的目的
Go GC 篇_哔哩哔哩_bilibili
【Golang】粗線條話GC(二)_哔哩哔哩_bilibili
Go 語言垃圾收集器的實作原理 | Go 語言設計與實作 (draveness.me)