[英]Why is compiling with CGO_ENABLED=0 slower?
When writing programs which utilize network, you can see quite noticeable slowdown of compilation with CGO_ENABLED=0
. 在编写利用网络的程序时,您可以看到CGO_ENABLED=0
的编译速度非常明显。
For example, the simplest HTTP server: 例如,最简单的HTTP服务器:
package main
import (
"flag"
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi! glad you requested %s.\n", r.URL.Path[1:])
}
func main() {
port := flag.Int("port", 9000, "")
flag.Parse()
http.HandleFunc("/", handler)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
if err != nil {
log.Fatal(err)
}
}
the timings are: 时间是:
% time go build
go build 0.46s user 0.06s system 131% cpu 0.396 total
% time CGO_ENABLED=0 go build
CGO_ENABLED=0 go build 3.93s user 0.15s system 143% cpu 2.849 total
So far I'm not using bindings to C so CGo handling or not seems irrelevant, what I'd like to do is to compile 100% static binary, but not if there's such slowdown. 到目前为止我没有使用绑定到C所以CGo处理或者似乎不相关,我想要做的是编译100%静态二进制,但如果有这样的减速则不行。
What is the cause of such behavior? 这种行为的原因是什么?
The problem is that the standard library packages are built without flags. 问题是标准库包是在没有标志的情况下构建的。 CGO_ENABLED
changes build flags and therefore it can't use the pre-built packages so most of the standard library needs to be rebuilt. CGO_ENABLED
更改了构建标志,因此无法使用预构建的包,因此需要重建大部分标准库。
As the other answer mentioned, go build -i
will install the packages built with the new flags, but that won't really solve much because if you install packages built with CGO_ENABLED=0
, it will speed up all future builds with CGO_ENABLED=0
, but it will slow down all the builds without it. 正如另一个提到的那样, go build -i
将安装使用新标志go build -i
的软件包,但这并没有真正解决,因为如果你安装使用CGO_ENABLED=0
构建的软件包,它将加速所有未来的构建, CGO_ENABLED=0
,但如果没有它,它将减慢所有构建。
Unfortunately the way pre-built packages are installed by default today is pretty inefficient because everything goes into the same directory under the same names regardless of how it's built. 不幸的是,今天默认安装预构建软件包的方式是非常低效的,因为无论它是如何构建的,所有内容都以相同的名称进入同一目录。 If you want to be able to have fast builds of go programs with different flags, besides doing go build -i
you also need to use the the -installsuffix
and/or the -pkgdir
flags. 如果你想能够使用不同的标志快速构建go程序,除了go build -i
之外,你还需要使用-installsuffix
和/或-pkgdir
标志。 In the system I work in, we have a handful of different compilation modes, each mode has different flags (because of a lot of old C code we interface with) and each mode also has its own -pkgdir
. 在我工作的系统中,我们有一些不同的编译模式,每种模式都有不同的标志(因为我们接口有很多旧的C代码),每种模式也都有自己的-pkgdir
。
This is the time spent re-building dependencies. 这是重建依赖项所花费的时间。 Go build by default does not save rebuilt dependencies. 默认情况下,Go build不会保存重建的依赖项。 See the -i
flag: The -i flag installs the packages that are dependencies of the target.
请参阅-i
标志: The -i flag installs the packages that are dependencies of the target.
Let's try your program with -i instead: 让我们用-i尝试你的程序:
$ time go build -i .
real 0m0.337s
user 0m0.343s
sys 0m0.121s
$ time CGO_ENABLED=0 go build -i .
real 0m2.135s
user 0m3.098s
sys 0m0.196s
$ time CGO_ENABLED=0 go build .
real 0m0.329s
user 0m0.367s
sys 0m0.085s
$ time go build .
real 0m2.588s
user 0m3.393s
sys 0m0.300s
The first time you switch cgo mode, it needs to rebuild dependencies. 第一次切换cgo模式时,需要重建依赖关系。 If you specify -i
, it will save them and the second build call will be much faster. 如果指定-i
,它将保存它们,第二次构建调用将更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.