我一直在尝试gc和gccgo,但遇到了一些奇怪的现象。
使用我曾经写过的program来测试一些定理,我得到了以下结果:(我删除了不必要的信息以提高可读性)
$ 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
我可以看到以下模式:
gccgo
构建的二进制文件的大小要小得多(并且剥离操作无助于改变这种差异)gc
构建的二进制文件执行gccgo
相比,使用gc
花费更多的时间我还测试了其他一些go程序(虽然不那么广泛),但它们都表现出相同的行为。
这似乎与this answer的陈述相矛盾:
我认为更多的优化意味着更快的二进制文件,同时需要更多的时间来编译...
这三种模式是什么原因?
最佳答案
有很多差异-bradfitz talked about some of them in a May 2014 talk:
gccgo
可以生成一个二进制文件,该二进制文件可以动态链接到libgo
,这会使输出变小,但意味着要在目标计算机上安装相关的库。没有cgo
的二进制文件没有此要求。 gccgo
进行了更多的低级优化,因为它可以使用gcc
的代码生成器和优化器。编写一些数据压缩代码后,gccgo的运行速度明显比gc
快。相同的优化也使编译器变慢:它正在做更多的工作。 gccgo
支持gcc
所支持的目标处理器,因此这是进入某些架构(如SPARC,ARMv8(64位)或POWER)的唯一方法。 (规范使用它来为arm64和ppc64编译其Juju服务编排工具。)gccgo
和gc
都支持ARMv7(32位),但是根据bradfitz的说法,gc
不会生成最有效的ARM代码。 gc
才有某些优化。new(T)
的返回值没有转义,它可能不会进行堆分配。)这减少了垃圾收集运行的频率。 .s
汇编器文件仅通过gc
链接,因此gccgo
默认不使用诸如Intel硬件CRC32C之类的东西(您必须提供专门针对gccgo的实现)。 gc
首先实现新的语言功能,通常比最新的gccgo
少一两个Go版本。