2014-11-21 103 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的基准测试系统而不是时间。

相关问题