Go 部落格
Go GC:優先考量低延遲和簡潔性
設定
Go 正在建立垃圾回收機制 (GC),不只適用於 2015 年,還有 2025 年,甚至更以後:它支援最新的軟體開發,並可以在未來十年內隨著新的軟體和硬體擴充。這樣的未來沒有停止世界的 GC 中斷,這一直阻礙 Go 等安全語言的更廣泛使用。
Go 1.5,首次看到這個未來的徵兆,GC 延遲時間遠低於一年前我們設定的 10 毫秒目標。在 Gophercon 的 演講 中我們提出一些令人印象深刻的數字。延遲時間的改良獲得廣泛的關注;羅賓·凡蘭根的部落格文章 每天數以十億計的請求進到 Go 1.5 用成果驗證我們的路線。我們特別喜歡 艾倫·薛瑞夫的作業伺服器圖表 和他的感想「85% 的聖潔減少」。
現今,16 GB RAM 的費用為 100 美元,而且 CPU 配備許多核心,每個核心配備多個硬體執行緒。在十年後,這些硬體將顯得古色古香,但現今用 Go 建立的軟體需要擴充才能滿足不斷擴張的需求和下一個重大的變革。由於硬體會提供提升通量所需的效能,Go 的垃圾收集器設計成有利於低延遲,且僅透過單一旋鈕進行調整。Go 1.5 便是邁向這條道路的第一大步,而這些第一步將永遠影響 Go 及其最佳支援的應用程式。這篇部落格文章將概要說明我們已針對 Go 1.5 收集器所做的工作。
特色
為了創造一個用於接下來十年的垃圾收集器,我們採用幾十年前的演算法。Go 的新垃圾收集器是一種並發、三色、標記清除收集器,此概念最早由 戴克斯特拉於 1978 年提出。這與現今大多數的「企業」等級垃圾收集器刻意區隔開來,我們相信這非常適合現代硬體的特性和現代軟體的延遲需求。
在三色收集器中,每個物件都是白色、灰色或黑色,我們將堆積視為連接物件的圖形。在 GC 週期開始時,所有物件都是白色的。GC 會拜訪所有根,即應用程式可以直接存取的物件,例如全域變數和堆疊中的項目,並將它們標記為灰色。然後,GC 會選擇一個灰色的物件,將之標記為黑色,然後掃描該物件以尋找指向其他物件的指標。當此掃描發現指向白色物件的指標時,它會將該物件標記為灰色。此程序會重複執行,直到沒有更多灰色的物件。此時,白色物件已知為無法到達,因此可以重複使用。
這一切都與應用程式發生,程式稱為mutator,它會在收集器執行期間變更指標。因此,mutator 必須維持不變性,亦即沒有任何黑色物件指向上一個白色物件,否則垃圾收集器將無法追蹤已安裝在堆積記憶體已拜訪過的部分內的一個物件。維護此項不變性是寫入障礙的工作,這是一個小功能,每當堆積記憶體中的指標被修改,mutator 都會執行。Go 的寫入障礙會對目前為白色,但現在可達得到物件設定灰色,藉此確保垃圾收集器最終會掃描指標。
判斷找出所有灰色物件的工作何時完成是一件困難的事,若要避免阻擋 mutator,這可能會很花錢又很複雜。為了讓事情簡單一點,Go 1.5 盡量同時執行許多工作,然後短暫停止運作,檢查所有灰色物件的潛在來源。找出此最終停止運作所需時間與此 GC 所執行總工作量之間的關鍵點,是 Go 1.6 的主要成果。
當然,魔鬼藏在細節裡。我們什麼時候開始執行 GC 週期?我們使用什麼指標來做出那個決定?GC 應該如何與 Go 排程器互動?我們如何暫停 mutator 執行緒,以便掃描其堆疊?我們如何表示白色、灰色和黑色,讓我們可以有效率地找出和掃描灰色物件?我們如何知道 root 在哪裡?我們如何知道指示物件在哪裡?我們如何將記憶體分段化降到最低?我們如何處理快取效能問題?堆積記憶體應該有多大?還有許多問題類似於配置、找出可存取物件、有些與排程相關,但許多與效能有關。每個領域的低量級討論都超出此部落格文章的範圍。
在進階的層面上,解決效能問題的一種方法是加入 GC 旋鈕,每個效能問題一個。然後,程式設計師可以轉動旋鈕尋找其應用程式的適當設定。缺點是若每年新增一或兩個旋鈕,十年後你就會面臨 GC 旋鈕轉動員就業法。Go 並沒有走上那條路。反而是提供一個稱為 GOGC 的旋鈕。此值會控制堆積記憶體的總大小,相對於可存取物件的大小。預設值 100 表示堆積記憶體總大小現在比上一次收集後的可存取物件大小大 100%(亦即兩倍)。200 表示堆積記憶體總大小比可存取物件大小大 200%(亦即三倍)。如果你要降低 GC 花費的總時間,就增加 GOGC。如果你要以更少的記憶體換取更多 GC 時間,就降低 GOGC。
更重要的是,隨著下一代硬體的 RAM 翻倍,只需讓 GOGC 翻倍就能將 GC 週期減半。另一方面,由於 GOGC 是基於可及物件大小,將可及物件翻倍就可以讓負載翻倍,無需重新調整。應用程式就這樣擴大了規模。此外,執行時期團隊不必持續支援數十個控制項而得以專注於根據實際客戶應用程式反應改善執行時期。
重點
Go 1.5 的 GC 預示著一個沒有暫停世界的將停頓不再是轉移到安全語言的屏障的未來。這是一個隨著硬體而輕鬆擴展應用的未來,隨著硬體更強大,GC 也不會阻礙更佳、更具可擴展性的軟體。這對於接下來的十年及以後來說是很好的一件事。如需有關 1.5 GC 及我們如何消除延遲問題的更多詳細資訊,請觀看 Go GC:延遲問題解決方案簡報 或 投影片。
下一篇文章:Golang 英國 2015
上一篇文章:發布 Go 1.5
部落格索引