為什麼go語言gc的時候要暫停整個程序?

使用一個或多個協程來垃圾回收不可以嗎?


Go GC: Solving the Latency Problem in Go 1.5

可以參考下這個。在stack scan階段有一小段stw,和mark termination階段要stw。之前要stw的mark和sweep階段都是並行的,不需要stw的了。

裡面也提到了1.5使用了write barrier的演算法會導致吞吐量下降,1.6會根據實際使用情況平衡下延遲和吞吐量。

沒有stw也是可以的,但吞吐量會進一步下降,未必是最佳選擇。


停下整個世界是為了保證收集時不產生新的垃圾,之後並發刪除是可以的,1.5可以實現


我對gc研究不是很多,說下我的理解

其實gc是可以不需要stw的,比如下面所描述的演算法

http://www.azulsystems.com/sites/default/files/images/c4_paper_acm.pdf

但基本上gc實現上都會有stw,就是成熟如jvm的hotspot也一樣,因為gc的吞吐量和暫停時間是一對矛盾體。通過stw可以儘快的標記,掃描出不可達對象,提高後期應用程序的吞吐量,但同時暫停時間又不能過長,所以gc演算法需要在兩者之間平衡。

go1.4的gc還不夠成熟,stw後標記所有不可達對象,然後start the world,清除操作是起goroutine和應用程序一起運行的,但stw有些場景時間過長導致需要優化程序

go1.5已經改善了不少,通過多次短時間的stw減少了stw時間的總長,但演算法複雜度提高了很多,隨著go的慢慢成熟,gc會做的更好,期待go的成長。

今天go1.5 beta已經出來了,可以體驗體驗。


就……程序沒寫好啊,慢慢改唄,不是說新版本已經並行GC了么?


不懂go 的gc,我來講一下.net的gc。clr gc也要suspend excution engine,gc完成之後再restart ee. 原因跟線程沒關係,gc是獨立的gc線程去完成的。suspend的原因是:gc帶來內存中對象address變化,如果此時不掛起,那麼上一秒還在讀取的對象,下一秒寫的時候寫到另一個對象里去了。因為可能大多數對象已經被move了。這跟線程鎖,臨界區是同樣的原理。不知道對樓主有沒有幫助。


樓上提到的CMS,也還是有stop the world的。通俗的說就是:你媽媽打掃你房間準備做一次徹底性清潔,你難道還能同時往地上隨意丟東西嗎?

試想如果你丟垃圾速度更快,比你媽媽掃地速度還快,那是不是垃圾最後堆滿了屋子?然後你媽媽也不幹了……最好的方法就是讓你安靜會,別丟垃圾了,起碼她老人家眼睛下一次性打掃完…

CMS更多引入分區標計回收概念,概念上跟一般並發數據結構集合處理的演算法差不多,把容器鎖在分區條件下細化…

當然STW永遠是垃圾回收語言的痛,高頻交易的場景下一次FULL GC帶來的STW駭人聽聞…


Stop the world 是為了避免gc自己gc


應該是所有的都要暫停一下, 不然gc邊回收, 用戶app邊跑, 會衝突


推薦閱讀:

如何評價 Go for android 或 Swift for web 這種現象?
為啥 Erlang 沒有像 Go、Scala 語言那樣崛起?
如何看待「Go 2.0」?
如何看待GO語言的新GC(TOC)?
這樣一段代碼在軟體工程界屬於什麼水平?

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