问题描述
在编写利用网络的程序时,可以看到 CGO_ENABLED = 0
的编译速度明显下降。
When writing programs which utilize network, you can see quite noticeable slowdown of compilation with CGO_ENABLED=0
.
例如,最简单的HTTP服务器:
For example, the simplest HTTP server:
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)
}
}
时间为:
% 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
到目前为止,我没有使用对C的绑定,因此CGo处理与否无关紧要,我想做的是编译100%静态二进制文件,但是如果出现这种情况,则不会。
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.
这种行为的原因是什么?
What is the cause of such behavior?
推荐答案
问题是标准库包的构建没有标记。 CGO_ENABLED
更改了构建标志,因此它不能使用预构建的包,因此大多数标准库都需要重新构建。
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.
作为另一个答案, go build -i
将安装使用新标志构建的软件包,但这并不能真正解决很多问题,因为如果您安装使用 CGO_ENABLED = 0
构建的软件包,它将使用 CGO_ENABLED = 0
加快以后的所有构建,但是会减慢速度没有它的所有构建。
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程序,除了执行 go build -i
外,还需要使用- installsuffix
和/或 -pkgdir
标志。在我使用的系统中,我们有几种不同的编译模式,每种模式都有不同的标志(因为我们要使用很多旧的C代码),并且每种模式也都有自己的 -pkgdir
。
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. 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
.
这篇关于为什么用CGO_ENABLED = 0编译会更慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!