Go 1.1的性能提升
注:今天上午在微博推薦了英文原文,感謝@Codefor 的熱心翻譯。如果其他朋友也有不錯的原創(chuàng)或譯文,可以嘗試推薦給我們。
——————————————————————–
這是Go1.1發(fā)布后性能提升分析系列的第一篇文章。
Go官方文檔(這里和 這里)報告說,用Go1.1重新編譯你的代碼就可以獲得30%-40%的性能提升。對linux/amd64平臺而言,有大量的評測可以證明上述性能提升,對linux/386和linux/arm類平臺,結(jié)果甚至更讓人驚訝。但是我暫時持保留意見。
關(guān)于gccgo,本系列重點關(guān)注提升Go1.1性能的gc系列編譯器(5g,6g和8g)。由于和gc編譯器共享相同的運行時和標(biāo)準(zhǔn)庫,gccgo間接受益于這些改進,但不作為本次基準(zhǔn)測試系列的重點。
Go1.1在編譯器,運行時和標(biāo)準(zhǔn)庫上有許多直接導(dǎo)致程序速度提升的特色改進,尤其是:
- 代碼生成優(yōu)化。涵蓋3個gc編譯器,包括更好的寄存器分配,減少不必要的間接加載,減少代碼量
- 內(nèi)聯(lián)優(yōu)化。包括部分內(nèi)置函數(shù)調(diào)用的內(nèi)聯(lián),處理接口轉(zhuǎn)換時編譯器生成的存根方法的內(nèi)聯(lián)。
- 減少棧使用。進而減輕棧大小的壓力,更少分裂棧。
- 引入并行垃圾收集器。收集器仍然是標(biāo)記-刪除,但是垃圾收集期間可以使用所有的CPU。
- 更精細(xì)的垃圾收集。減少堆的大小,進而獲得更低的GC延時
- 新的運行時調(diào)度器。在調(diào)度goroutine時做出更好的決策。
- 調(diào)度器和net包整合的更緊密。大幅減少包處理的延時并獲得更高的吞吐。
- 部分運行時和標(biāo)準(zhǔn)庫用匯編重寫。利用特定的移動或密碼指令的優(yōu)勢。
autobench介紹
沒有事實依據(jù)的不可復(fù)現(xiàn)的評測比任何事情都讓我不滿。由于這個系列要列出大量的數(shù)字,給出一些強有力的結(jié)論,對我而言,有必要提供一個渠道,大家可以在自己機器上驗證我的結(jié)果。
為此,我已經(jīng)建立了一個簡單的基于make的工具,用于比較Go1.0和Go1.1在一系列綜合基準(zhǔn)測試中的性能。它可以運行在任何Go支持的任何平臺上。雖然該項目仍處于開發(fā)階段,它已經(jīng)產(chǎn)生了很多有用的數(shù)據(jù)。這些數(shù)據(jù)存放在代碼庫中。你可以在GitHub找到這個項目:
https://github.com/davecheney/autobench
我要感謝那些從自己機器提交基準(zhǔn)測試結(jié)果數(shù)據(jù)的Go社區(qū)的成員,這使得我對Go1.1的相對性能做出明智的結(jié)論。
如果你對參與autobench感興趣,很快將有一個記錄Go1.1性能的分支產(chǎn)生。
一圖勝千言萬語
為了更好的展示基準(zhǔn)測試結(jié)果,AJ Starks 已經(jīng)開發(fā)了一個好用的工具。benchviz 可以將misc/benchcmp枯燥的基于文本的輸出轉(zhuǎn)換成漂亮的圖表。你可以在AJ的博客上看到所有關(guān)于benchviz 的信息。
http://mindchunk.blogspot.com.au/2013/05/visualizing-go-benchmarks-with-benchviz.html
在傳統(tǒng)的misc/benchcmp工具之后,對所有的改進,當(dāng)運行時間的減少,或者吞吐的增加,以條狀圖的形式向右擴展,反之,向左收縮。
Go1 在linux/amd64平臺基準(zhǔn)測試
這篇文章的剩余部分將會集中在linux/amd64的性能評測。6g編譯器被認(rèn)為是gc編譯器包中的旗艦編譯器。除了在前后端的代碼生成優(yōu)化,標(biāo)準(zhǔn)庫和運行時的性能敏感部分已經(jīng)用匯編重寫以充分利用SSE2指令。 這篇文章接下來的數(shù)據(jù)來自此結(jié)果文件 linux-amd64-d5666bad617d-vs-e570c2daeaca.txt
Go1基準(zhǔn)測試包是一個綜合的基準(zhǔn)測試,它試圖獲取真實世界中標(biāo)準(zhǔn)庫中的主要包的使用情況。總體上,這個結(jié)果支持之前30%-40%性能提升的結(jié)論。通過查看提交到autobench庫中的結(jié)果,很明顯GobDecode和Gzip性能有所退步,并且問題 5165 和 5166 都產(chǎn)生了。相對而言,后者的罪魁禍?zhǔn)讘?yīng)該至少部分歸于遷移到64位int 。
net/http 基準(zhǔn)測試
這一系列的基準(zhǔn)測試是從net/http包中抽出來的,它展示了Brad Fitzpatrick 和Dmitry Vyukov以及許多其他人貢獻到net和net/http包中的工作。
這個系列的基準(zhǔn)測試中需要指出的是,ReadRequest(用于解包一個HTTP請求)的性能提升。ClientServerParallel基準(zhǔn)測試目前并不能在所有的amd64平臺運行,因為部分amd64平臺還不支持新的和net聚合的運行時。完成剩余的BSD和Windows平臺的支持是 1.2周期的重點。
#p#
Runtime 微基準(zhǔn)測試
在這里展示的最后一個基準(zhǔn)測試是從runtime包中抽取的。
Runtime基準(zhǔn)測試展示了runtime包非常低層次部分的微型基準(zhǔn)測試。
上面明顯的衰退就是第一個Append基準(zhǔn)測試。然而在實際時間中,基準(zhǔn)測試卻從36ns/op提升到100ns/op,這意味著,對于某些append使用場景是存在性能衰退的。這可能已經(jīng)在建議CL 9360043中指出。
Runtime基準(zhǔn)測試中最大的贏家就是驚人的map。新的map代碼由khr在issue 3886聲明并貢獻。包括Channel操作的開銷減少(感謝Dmitry的新調(diào)度器),涉及complex128操作的優(yōu)化,以及用64位匯編重寫的hash和內(nèi)存移動操作的提速。
結(jié)論
對于運行現(xiàn)代64位intelCPU的linux/amd64平臺,6g編譯器和運行時可以生成顯著高校的代碼。其他的amd64平臺也有類似的提升,具體的提升程度會有變化。如果你有能力,我鼓勵你審閱autobench代碼庫中的基準(zhǔn)測試數(shù)據(jù),并提交你自己的結(jié)果數(shù)據(jù)。
在接下來的文章中,我會著重在Go1.1給386和arm平臺帶來的性能提升。
英文原文:Dave Cheney