Go 部落格

Go 執行時期:4 年後

Michael Knyszek
2022年 9 月 26 日

自我們2018 年關於 Go GC 的最後一篇部落格文章以來,Go GC 和更廣泛的 Go 執行時期已持續改善。我們已解決了一些大型專案,靈感來自真實世界的 Go 程式和 Go 使用者所面臨的真實挑戰。讓我們告訴您重點內容!

有何新功能?

這些變更對於使用者而言大多是不顯而易見的:他們認識也喜愛的 Go 程式碼只需透過升級 Go 就能執行得更好。

一個新功能

隨著 Go 1.19 推出的一項廣受期待的功能,僅需一點額外的作業就能使用,並承載了廣大的潛能:Go 執行時期的軟性記憶體限制。

多年來,Go GC 僅有一個調整參數:GOGC。透過 GOGC,使用者可以調整 Go GC 所做的 CPU 額外負擔和記憶體額外負擔之間的權衡。多年來,這個「功能」已為 Go 社群提供了良好的服務,涵蓋了廣泛的用例。

Go 執行時期團隊一直不願意在 Go 執行時期中新增新的功能,原因很充分:每個新功能都代表著設定空間中的一個新面向,而我們可能永遠需要測試和維護這些面向。功能的擴增也為 Go 開發人員帶來了理解和有效使用這些功能的負擔,功能越多,負擔就越重。因此,Go 執行時期一直傾向於在最小設定下保持合理的行為。

那麼,為什麼要增加一個記憶體限制功能呢?

記憶體不像 CPU 時間一樣有彈性。CPU 時間而言,如果你稍等一下,未來總會有更多。不過記憶體而言,你所擁有的有限制。

記憶體限制解決了兩個問題。

第一個是當應用程式高峰記憶體使用無法預估時,GOGC 本身幾乎無法保護不出現記憶體不足的問題。只有 GOGC,Go 執行時間單純不知道它有多少可用記憶體。設定記憶體限制使執行時間能堅固面對暫時、可復原的負載量飆升,使執行時間知道什麼時候需要更加努力才能減少記憶體開銷。

第二個是為了避免於不使用記憶體限制的情況下發生記憶體不足的錯誤,GOGC 必須根據高峰記憶體進行調整,這會讓 GC CPU 開銷變得更大以維持較低的記憶體開銷,即使應用程式並未達高峰記憶體使用量且還有許多可用記憶體。這在我們這個有容器的世界中特別切題,程式會被放入有特定且獨立記憶體預約的盒子中,我們大可好好利用!藉由提供對負載量飆升的保護,設定記憶體限制讓 GOGC 能在 CPU 開銷方面更積極地調整。

記憶體限制的設計易於採用且堅固。例如,這是對應用程式的 Go 部分的整體記憶體使用量的限制,而非僅 Go 堆疊,因此使用者不必擔心計算 Go 執行時間的開銷。執行時間也會調整其記憶體清除政策以響應記憶體限制,因此會在記憶體壓力下更積極地將記憶體傳回給作業系統。

不過,儘管記憶體限制是一種強大的工具,仍必須小心使用。一個重大的警告是它讓你的程式容易發生 GC 激增:這種狀態會讓程式花太多時間執行 GC,導致沒有足夠的時間進行有意義的進度。例如,如果為 Go 程式設定的記憶體限制低於程式實際需要的記憶體,程式可能會激增。GC 激增在過去不太可能發生,除非 GOGC 明確大幅調整,特別偏向於記憶體使用。我們選擇優先出現記憶體不足而非激增,因此作為緩解措施,執行時間會將 GC 限制在總 CPU 時間的 50%,即使這表示超過記憶體限制。

需要考量的內容很多,因此作為這項工作的一部分,我們發布了 全新 GC 指南,包含互動視覺化內容來協助你了解 GC 成本以及如何控制成本。

結論

試試記憶體限制!在製作時使用!閱讀 GC 指南

我們一直在尋找如何改善 Go 的回饋,不過聽到 Go 對你的運作正常,也有助益。 傳送回饋 給我們!

下一篇文章:Go 十三年的歷史
上一篇文章:Go 開發人員調查 2022 年第 2 季結果
部落格索引