2014-11-21 100 views
5

我一直在嘗試使用gc和gccgo,並且遇到一些奇怪的行爲。爲什麼使用gccgo構建的二進制文件更小(其他區別?)

使用program我曾經寫過測試一些定理,我得到了這些結果:(我刪除了readablitity不必要的信息)

$ time go build -compiler gc -o checkprog_gc checkprog.go (x 3) 
go build <...> 0.13s user 0.02s system 100% cpu 0.149 total 
go build <...> 0.13s user 0.01s system 99% cpu 0.148 total 
go build <...> 0.14s user 0.03s system 100% cpu 0.162 total 
--> average:  0.13s user 0.02s system 100% cpu 0.153 total 


$ time go build -compiler gccgo -o checkprog_gccgo checkprog.go (x 3) 
go build <...> 0.10s user 0.03s system 96% cpu 0.135 total 
go build <...> 0.12s user 0.01s system 96% cpu 0.131 total 
go build <...> 0.10s user 0.01s system 92% cpu 0.123 total 
--> average:  0.11s user 0.02s system 95% cpu 0.130 total 


$ strip -s -o checkprog_gc_stripped checkprog_gc 
$ strip -s -o checkprog_gccgo_stripped checkprog_gccgo 

$ ls -l 
1834504 checkprog_gc* 
1336992 checkprog_gc_stripped* 
    35072 checkprog_gccgo* 
    24192 checkprog_gccgo_stripped* 

$ time ./checkprog_gc 
./checkprog_gc 6.68s user 0.01s system 100% cpu 6.674 total 
./checkprog_gc 6.75s user 0.01s system 100% cpu 6.741 total 
./checkprog_gc 6.66s user 0.00s system 100% cpu 6.643 total 
--> average: 6.70s user 0.01s system 100% cpu 6.686 total 

$ time ./checkprog_gccgo 
./checkprog_gccgo 10.95s user 0.02s system 100% cpu 10.949 total 
./checkprog_gccgo 10.98s user 0.01s system 100% cpu 10.964 total 
./checkprog_gccgo 10.94s user 0.01s system 100% cpu 10.929 total 
--> average  10.96s user 0.01s system 100% cpu 10.947 total 

我可以看到下面的模式:內置

  1. 二進制與gccgo的大小從根本上小(剝離無助於改變這種差異)與gc內置
  2. 二進制文件可以更快地執行
  3. 它需要更多的時間來建立與gccgogc

我還測試了一些其他的圍棋程序(而不是廣泛地),他們都表現出相同的行爲。

這似乎矛盾的時候,this answer狀態:

簡而言之:gccgo:更多的優化,更多的處理器。

我認爲更多的優化意味着更快的二進制文件,而需要更多的時間來編譯......

是什麼原因這三種模式?

+2

很可能是因爲它們鏈接到'libgo'。 'ldd'或'readelf'會告訴你(如果你在Linux系統上)。 – kostix 2014-11-21 18:06:56

回答

7

有一堆differences-- bradfitz talked about some of them in a May 2014 talk

  • gccgo可以產生一個二進制,在libgo動態鏈接,這使得輸出小而是指被在目標機器上安裝的相關庫。去沒有cgo的二進制文件沒有這個要求。
  • gccgo確實更低級優化'因爲它可以使用gcc的碼發生器和優化器。編寫一些數據壓縮代碼,gccgo運行速度明顯快於gc。這些相同的優化使編譯器變得更慢:它正在做更多的工作。
  • gccgo支持gcc所做的目標處理器,因此它是搭建像SPARC,ARMv8(64位)或POWER等體系結構的唯一方法。 (Canonical使用它來編譯它們的Juju服務編排工具,用於arm64和ppc64)。
  • gccgogc都支持ARMv7(32位),但根據bradfitz的說法gc並不生成最有效的ARM代碼。
  • 只有gc有某些優化。
    • 一個很大的問題是escape analysis,其中編譯器確定某些變量永遠不會「轉義」分配它們的函數,因此可以進行堆棧分配。 (所以,令人驚訝的是,如果它的返回值沒有轉義,new(T)可能不會堆分配。)這減少了垃圾收集需要運行的頻率。
    • 另一個是彙編文件在標準庫中只有gc鏈接,所以像默認情況下(你必須提供專門爲gccgo實現的實現),英特爾硬件CRC32C等一些東西不被gccgo使用。
  • gc首先實現新的語言功能,並且通常是最新的gccgo之前的小版本Go版本。
+0

(做了這個CW'因爲可能有很多關於gc/gccgo差異的說法,我並不是真正的專家,而且我很想知道更多的人來編輯它。) – twotwotwo 2014-11-21 19:21:09

6

大小不同,因爲GC使靜態的二進制文件和gccgo鏈接libgo。這意味着整個運行時(調度程序,垃圾回收器,地圖,通道)的代碼不在gccgo創建的最終二進制文件中。

編譯的速度當然有利於gc。 GC是在編譯速度的基礎上構建的。它通常還會減少代碼的優化次數,並減少需要執行的工作。

現在爲什麼gc仍然更快。事實是,他們都不會比其他人快。例如,嘗試使用md5文件,GCCGO將快一個數量級。嘗試實施具有很多渠道的東西,gc肯定會獲勝。你不能總是提前知道哪些會成功。 GC往往具有更高的併發性,而gccgo在數學上往往更好。但是,這是您需要根據具體情況進行測試的情況。最好使用go test的基準測試系統而不是時間。

相關問題