Go1.6與JVM CMS的記憶體回收對比

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

自從Go1.5引入了真正的並發GC後, Go1.6進一步進行了最佳化,使得Go在上百G級的堆大小時依然能將STW時間控制在20ms以內:

而Java8的G1收集器,預設參數下在100G以上的heap下,會造成秒級的STW。雖然可以通過-XX:MaxGCPauseMillis調整,但是是以犧牲大量輸送量為代價。這裡淺析一下Go能做到比G1更短的STW的原因。

輪流掛起協程

JVM的CMS收集器在工作時,大致分為4個階段:

  1. 初始標記
  2. 並發標記
  3. 重新標記
  4. 並發清除

其中1, 3 是需要STW的階段,CMS的停頓也是由這2個階段引發的。Go1.5中的CMS也分為這些階段,其中1, 3同樣需要STW。那為什麼Go會停頓時間更少呢?原因是,Go的CMS在第3階段並不是掛起所有goroutine,而是輪流掛起。如此一來,3階段就不會造成整個程式的停頓,從而就沒有算入到STW時間之中。

Go觸發GC的時機

Go的gc觸發條件也與JVM的gc有很大區別。JVM通常是堆的使用到達某一閥值,或發生new操作失敗時gc。而Go則是當從上次gc以來,新建立的對象大小等於上次gc以後存活下來的對象時觸發gc. 這樣,每次gc的壓力就不會像JVM那麼大,STW時間理所當然會短很多,但也犧牲了輸送量。

Go比Java產生更少的記憶體垃圾

Go的對象(即struct類型)是可以分配在棧上的。Go會在編譯時間做靜態逃逸分析(Escape Analysis), 如果發現某個對象並沒有逃出當前範圍,則會將對象分配在棧上而不是堆上,從而減輕了GC壓力。其實JVM也有逃逸分析,但與Go不同的是Java無法在編譯時間做這項工作,分析是在運行時完成的,這樣做一是會佔用更多的CPU時間,二是不可能會把所有未逃逸的對象都最佳化到棧中。

到目前為止,Go的運行效率並沒有因為執行的是本地機器碼而體現出比Java更好的效能優勢,我想這並不怪go, 而是JVM在JIT的協助下其效能已經非常好了。雖然如此,Go的最佳化空間會比JVM更大。相信未來Go的效能會不斷提升,終究會超過JVM。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.