为了账号安全,请及时绑定邮箱和手机立即绑定

为什么用 gccgo 构建的二进制文件更小

为什么用 gccgo 构建的二进制文件更小

Go
倚天杖 2021-08-30 21:51:50
我一直在试验 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 totalgo build <...>    0.13s user 0.01s system 99%  cpu 0.148 totalgo 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 totalgo build <...>    0.12s user 0.01s system 96% cpu 0.131 totalgo 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 程序(虽然不是那么广泛),但它们都表现出相同的行为。这似乎与这个答案所说的相矛盾:简而言之:gccgo:更多优化,更多处理器。我认为更多的优化意味着更快的二进制文件,同时需要更多的时间来编译......这三种模式的原因是什么?
查看完整描述

2 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

有很多不同之处——布拉菲茨在 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默认情况下不使用诸如英特尔硬件 CRC32C 之类的东西(您必须专门为 gccgo 提供实现)。

  • gc首先实现新的语言功能,并且通常比最新的gccgo.


查看完整回答
反对 回复 2021-08-30
?
皈依舞

TA贡献1851条经验 获得超3个赞

大小不同,因为 gc 生成静态二进制文件,而 gccgo 链接到 libgo。这意味着整个运行时(调度程序、垃圾收集器、映射、通道)的代码不在 gccgo 创建的最终二进制文件中。

编译速度当然有利于gc。GC 的构建考虑了编译速度。它还通常会生成较少优化的代码,并且需要执行的工作较少。

现在讨论为什么 gc 仍然更快。事实是,它们中的任何一个都不总是比另一个快。例如,尝试 md5 一个文件,GCCGO 会快一个数量级。尝试用很多通道来实现一些东西,gc 肯定会赢。你不能总是提前知道哪个会成功。GC 往往具有更高效的并发性,而 gccgo 往往更擅长数学。但是,这是您需要根据具体情况进行测试的。最好使用 go test 的基准测试系统而不是时间。


查看完整回答
反对 回复 2021-08-30
  • 2 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信