如何看待GO語言的新GC(TOC)?

Transaction Oriented Collector (TOC) - Go"s next GC

golang.org/s/gctoc contains an overview


謹慎樂觀。首先這不是一個全新GC, 而是原有GC上加的一個新優化路徑。TOC要解決的問題或者背景假設是很經典的,用正常人的話來說就是:「程序執行中產生的大部分對象的生命周期都很短,而且都只在局部使用。」基於局部使用假設,首先可以做的是靜態的逃逸分析,在編譯期就指出很大一部分對象的生命周期,這個 Go 也已經做了,而且還在優化。至於不能在編譯期確定生命周期的,在運行時的垃圾回收中很常見的做法就是分代 GC, 讓年輕對象更快更容易回收,降低全局 GC 壓力。

而 TOC 基於的假設是上面短生命周期假設的一個特化版本:

  1. 絕大部分事務(比如一個 HTTP 請求處理)都是短事務。
  2. 每個事務開一個新的 goroutine 來處理,處理完 goroutine 結束。
  3. 執行期間產生的大部分對象都只在goroutine內部使用。

那麼,如果可以準確標記哪些對象是跨 goroutine 共享了,那在goroutine結束的時候把沒有共享出去的全回收掉就可以了。實現一個準確及時回收內存還能用好多核還性能好的分代GC非常複雜,還要針對各種場景優化,我記得 golang-dev 郵件組討論過要不要實現分代 GC, 不過看來結論是 TOC 了,TOC其實就是一個基於特化假設的特化簡單實現,這很 gopher.

一個對象有沒有跨goroutine共享出去(文檔里的publish)是有傳遞關係的,你被一個published的對象引用了那你和所有你引用的對象也published了,如果我沒看錯,現在的設計是要在write barrier上遞歸標記這個狀態的。我會擔心這樣下來是否會有一些場景的運行時開銷比原來更大了。TOC 對它要優化的場景應該是能同時實現提高吞吐(降低運行時開銷),降低停頓時間和節省內存佔用的目標的,還能在多核環境高效擴展,而這個場景也確實是網路服務中的統治性場景。但還是要看有沒有被嚴重劣化的場景,以及最後真實服務的綜合效能。

這種運行時優化的東西,現在已經很難有一個超級聰明的想法然後秒殺所有前人成果了,都是針對實用場景優化,很多時候只要運行時數據擺在你面前,解決方法是顯而易見的。我一直對 Go 的運行時優化持樂觀態度,並不是因為有大牛操刀,而是因為他們可以從Google內部機群拿到巨量的運行時數據來支持設計決策和測試新想法。保持簡單,看實際環境數據做優化,這個大方向是靠譜的。


看了一下介紹文檔,粗淺的理解是,有點類似erlang的單Process獨立垃圾回收。不同之處是,erlang Process內存不能共享,可以完全獨立回收;而,golang goroutine是可以共享內存的,不能完全獨立回收,但是可以使用單個goroutine的內部申請且不暴露給其他goroutone的內存信息來輔助GC的實現,因為這部分內存在goroutine終止以後是可以直接回收的。


應該不會比go原來的gc更差吧!(這可能是個flag)


推薦閱讀:

這樣一段代碼在軟體工程界屬於什麼水平?
現在想再學習一門編程語言,應該選擇go還是python?
Golang 的並發與 Erlang、Scala、Node.js 和 Python 的並發模型相比有何特點?
為什麼用golang作為遊戲服務端的開發語言,它的並發性如何?golang有什麼優點?
golang的goroutine是如何實現的?

TAG:GC垃圾回收計算機科學 | Go語言 |