我一直在试验gc和gccgo,我遇到了一些奇怪的行为.
使用我曾编写的程序来测试一些定理,我得到了这些结果:(我删除了不必要的信息以获得可读性)
$ 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
Run Code Online (Sandbox Code Playgroud)
我可以看到以下模式:
gccgo大小要小得多(并且剥离无助于改变这种差异)gc执行速度更快gccgo比使用它需要更多的时间gc我还测试了其他一些go程序(虽然不是那么广泛),但它们都表现出相同的行为.
这似乎与这个答案所说的相矛盾:
简而言之:gccgo:更多优化,更多处理器.
我认为更多的优化意味着更快的二进制文件,同时需要更多的时间来编译...
这三种模式的原因是什么?
有一堆差异 - 布拉德菲茨在2014年5月的一次谈话中谈到了其中的一些:
gccgo可以生成动态链接的二进制文件libgo,这会使输出更小,但意味着要在目标计算机上安装相关的库.去二进制文件没有cgo没有这个要求.gccgo进行更多的低级优化,因为它可以使用gcc代码生成器和优化器.编写一些数据压缩代码,gccgo的运行速度明显快于gc.这些相同的优化使编译器变慢:它正在做更多的工作.gccgo支持目标处理器gcc,因此它是获得某些体系结构的唯一方法,如SPARC,ARMv8(64位)或POWER.(Canonical使用它为arm64和ppc64编译他们的Juju服务编排工具.)gccgo并且gc都支持ARMv7(32位),但根据bradfitz的讲话gc并没有生成最有效的ARM代码.gc.
new(T)如果其返回值不会转义,则可能无法进行堆分配.)这会减少垃圾收集需要运行的频率..s标准库中的汇编程序文件只链接gc,因此gccgo默认情况下不使用Intel硬件CRC32C之类的东西(您必须提供专门用于gccgo的实现).gc首先实现新的语言功能,并且通常是最新的一个或两个Go版本gccgo.大小不同,因为gc生成静态二进制文件和gccgo链接到libgo.这意味着整个运行时(调度程序,垃圾收集器,映射,通道)的代码不在gccgo创建的最终二进制文件中.
编译的速度当然会有利于gc.GC的构建考虑了编译速度.它通常也会使代码更少优化,并且需要执行的工作量更少.
现在,为什么gc仍然更快.事实是,它们都不比另一个更快.例如,尝试md5文件,GCCGO将快一个数量级.尝试用很多频道实现一些东西,gc一定会赢.你不能总是提前告诉谁会成功.GC往往具有更高效的并发性,gccgo往往更好于数学.但是,这是您需要根据具体情况进行测试的内容.最好使用go test的基准测试系统而不是时间.