Go 1.1 效能提升 —— 第1部分

類別: IT

這是第一次在一系列的文章中分析Go 1.1中對效能的改進。

早先已有報導(這裡,和這裡),只須簡單的使用Go 1.1重新編譯性一下你的程式碼,就能提升30-40%的效能。在linux/amd64平臺中,這已被廣泛的基準測試所支援。在linux/386和linux/arm平臺中,這個結果甚至更加優秀,但這是末倒置的。

gccgo的注意事項。這一系列(series)重點在於GC系列編譯器對Go 1.1效能改進(5g,6g和8g)的貢獻。gccgo從這些改進中間接受益,因為它共享相同的執行時(runtime)和標準庫(tandard library),但不是這一基準測試系列(benchmarking series)的焦點。

Go1.1在編譯器,執行時和標準庫上有許多直接導致程式速度提升的特色改進,特別是:

  • 程式碼生成優化。涵蓋3個gc編譯器,包括更好的暫存器分配,減少不必要的間接載入,減少程式碼量
  • 內聯優化。包括部分內建函式呼叫的內聯,處理介面轉換時編譯器生成的存根方法的內聯。
  • 減少棧使用。進而減輕棧大小的壓力,更少分裂棧。
  • 引入並行垃圾收集器。收集器仍然是標記-刪除,但是垃圾收集期間可以使用所有的CPU。
  • 更精細的垃圾收集。減少堆的大小,進而獲得更低的GC延時
  • 新的執行時排程器。在排程goroutine時做出更好的決策。
  • 排程器和net包整合的更緊密。大幅減少包處理的延時並獲得更高的吞吐。
  • 部分執行時和標準庫用匯編重寫。利用特定的移動或加密指令的優勢。

autobench介紹

沒有事實依據的不可復現的評測比任何事情都讓我不滿。由於這個系列要列出大量的數字,給出一些強有力的結論,對我而言,有必要提供一個渠道,大家可以在自己機器上驗證我的結果。

為此,我已經建立了一個簡單的基於make的工具,用於比較Go1.0和Go1.1在一系列綜合基準測試中的效能。它可以執行在任何Go支援的任何平臺上。雖然該專案仍處於開發階段,它已經產生了很多有用的資料。這些資料存放在程式碼庫中。你可以在GitHub找到這個專案:

https://github.com/davecheney/autobench

我要感謝那些從自己機器提交基準測試結果資料的Go社群的成員,這使得我對Go1.1的相對效能做出明智的結論。

如果你對參與autobench感興趣,很快將有一個記錄Go1.1效能的分支誕生。

一張圖勝過千言萬語

為了更好的展示基準測試結果,AJ Starks 已經開發了一個好用的工具。benchviz 可以將misc/benchcmp枯燥的基於文字的輸出轉換成漂亮的圖表。你可以在AJ的部落格上看到所有關於benchviz 的資訊。

http://mindchunk.blogspot.com.au/2013/05/visualizing-go-benchmarks-with-benchviz.html

在傳統的misc/benchcmp工具之後,對所有的改進,當執行時間的減少,或者吞吐的增加,以條狀圖的形式向右擴充套件,反之,向左收縮。

Go1 在linux/amd64平臺基準測試

這篇文章的剩餘部分將會集中在linux/amd64的效能評測。6g編譯器被認為是gc編譯器包中的旗艦編譯器。除了在前後端的程式碼生成優化,標準庫和執行時的效能敏感部分已經用匯編重寫以充分利用SSE2指令。 

這篇文章接下來的資料來自此結果檔案 linux-amd64-d5666bad617d-vs-e570c2daeaca.txt

bm0

Go1基準測試包是一個綜合的基準測試,它試圖獲取真實世界中標準庫中的主要包的使用情況。總體上,這個結果支援之前30%-40%效能提升的結論。通過檢視提交到autobench庫中的結果,很明顯GobDecode和Gzip效能有所退步,並且問題 5165 和 5166 都產生了。相對而言,後者的罪魁禍首應該至少部分歸於遷移到64位int 。

net/http包基準測試

這一系列的基準測試是從net/http包中抽出來的,它展示了Brad Fitzpatrick 和Dmitry Vyukov以及許多其他人貢獻到net和net/http包中的工作。

bm2

這個系列的基準測試中需要指出的是,ReadRequest(用於解包一個HTTP請求)的效能提升。ClientServerParallel基準測試目前並不能在所有的amd64平臺執行,因為部分amd64平臺還不支援新的和net聚合的執行時。完成剩餘的BSD和Windows平臺的支援是 1.2週期的重點。

Runtime 微基準測試

在這裡展示的最後一個基準測試是從runtime包中抽取的。

bm1

Runtime基準測試展示了runtime包非常低層次部分的微型基準測試。

上面明顯的衰退就是第一個Append基準測試。然而在實際時間中,基準測試卻從36ns/op提升到100ns/op,這意味著,對於某些append使用場景是存在效能衰退的。這可能已經在建議CL 9360043中指出。

Runtime基準測試中最大的贏家就是驚人的map。新的map程式碼由khr在issue 3886宣告並貢獻。包括Channel操作的開銷減少(感謝Dmitry的新排程器),涉及complex128操作的優化,以及用64位彙編重寫的hash和記憶體移動操作的提速。

結論

對於(執行於)現代的(modern)Intel 64位CPU中的linux/amd64平臺,6g編譯器與執行時(runtime),顯著帶來更快的程式碼(執行速度)。其它amd64平臺有類似的速度提升,雖然具體的改進有所不同。我鼓勵你重新檢視autobench知識庫(repository)中的基準測試資料,並且如果有能力的話,提交你自已的結果。

在隨後的文章中,我將探討Go 1.1對386和arm 平臺帶來的性能提升。

Go 1.1 效能提升 —— 第1部分原文請看這裡

推薦文章