Go 部落格
Go 執行時期:4 年後
自我們2018 年關於 Go GC 的最後一篇部落格文章以來,Go GC 和更廣泛的 Go 執行時期已持續改善。我們已解決了一些大型專案,靈感來自真實世界的 Go 程式和 Go 使用者所面臨的真實挑戰。讓我們告訴您重點內容!
有何新功能?
-
sync.Pool
,用於重複使用記憶體的 GC 感知工具,具備較低的延遲影響,並且比以前能更有效回收記憶體。(Go 1.13) -
Go 執行時期會更主動地將不需要的記憶體傳回作業系統,減少過量記憶體消耗和發生記憶體不足錯誤的機率。這樣可以將閒置記憶體消耗減少多達 20%。 (Go 1.13 和 1.14)
-
Go 執行時期能在更多情況下預先搶佔 goroutine,將停止整個世界的延遲降低多達 90%。在此觀看 Gophercon 2020 的演講。 (Go 1.14)
-
Go 執行時期比以前能更有效率地管理計時器,特別是在具備多個 CPU 核心之機器上。(Go 1.14)
-
延遲聲明現已於大多數情況下,以一般的函數呼叫所產生的成本為準。 在此觀看 Gophercon 2020 會議影片。 (Go 1.14)
-
記憶體配置器的慢速路徑 大幅縮減 改善與 CPU 核心間的搭配,將處理量提高多達 10%,並將尾延遲時間減少多達 30%,尤其是在高度平行的程式中。(Go 1.14 和 1.15)
-
透過新的 runtime/metrics 套件,我們現可更精細、靈活且有效地存取 Go 記憶體統計資料。進而將取得執行時間統計資料的延遲時間降低兩個數量級 (毫秒縮減至微秒)。 (Go 1.16)
-
Go 排程器現可將最高 30% 的 CPU 時間空出來尋找新的工作。 (Go 1.17)
-
Go 程式碼現遵循 amd64、arm64 和 ppc64 上的基於暫存器的呼叫慣例,進而將 CPU 效率提升多達 15%。 (Go 1.17 和 Go 1.18)
-
Go GC 的內部會計和排程已被 重新設計,解決了與效率和健全性相關的各種長期問題。這可大幅降低應用程式尾延遲時間 (最高減少 66%),且此類應用程式的 goroutine 堆疊已佔用大量記憶體。 (Go 1.18)
-
當應用程式處於閒置狀態時,Go GC 現可限制 其自身的 CPU 使用。這將讓執行 GC 週期的 CPU 使用率降低 75%,進而減少會讓工作管理程式感到混淆的 CPU 尖峰。 (Go 1.19)
這些變更對於使用者而言大多是不顯而易見的:他們認識也喜愛的 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 季結果
部落格索引