2017-12-08 20 views
0

ネットワークを利用したプログラムを書くときには、CGO_ENABLED=0でかなりコンパイルが遅くなることがわかります。なぜCGO_ENABLED = 0でコンパイルするのが遅いのですか?

例えば、最も単純な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) 
    } 
} 

タイミングは以下のとおりです。

% 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 

CGOハンドリングかは無関係と思われるので、これまでのところ、私は何を私は、Cへのバインディングを使用していませんよ100%の静的バイナリをコンパイルすることができますが、そのようなスローダウンがある場合はそうではありません。

このような現象の原因は何ですか?

答えて

2

問題は、標準ライブラリパッケージがフラグなしでビルドされていることです。 CGO_ENABLEDはビルドフラグを変更するので、あらかじめ構築されたパッケージを使用することはできませんので、ほとんどの標準ライブラリを再構築する必要があります。言及された他の答えとして

go build -iは新しいフラグで構築されたパッケージをインストールしますが、それは本当にあなたがCGO_ENABLED=0で構築されたパッケージをインストールした場合、それは将来のすべてがCGO_ENABLED=0でビルドをスピードアップしますので、多くを解決するが、それはありませんそれなしですべてのビルドを遅くします。

残念ながら、今日のデフォルトでは、ビルドされたパッケージがインストールされる方法は、ビルド方法にかかわらず同じ名前の同じディレクトリにすべて格納されるため、かなり非効率的です。異なるフラグを持つプログラムを高速にビルドするには、go build -iのほかに、-installsuffixおよび/または-pkgdirフラグも使用する必要があります。私が働いているシステムでは、いくつかの異なるコンパイルモードがあります。各モードには異なるフラグがあります(古いCコードとのインターフェイスが多いため)。各モードには独自の-pkgdirもあります。

+0

Btwは1.10のキャッシュのように見えますが、多くを助けるつもりです... ( '' pkg/'を完全に取り除く将来計画もあります。 ) –

1

これは、依存関係の再構築に費やされた時間です。 デフォルトでビルドを行っても、再構築された依存関係は保存されません。 -iフラグを参照してください: The -i flag installs the packages that are dependencies of the target.

にの代わりに-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 

あなたはCGOモードを切り替える初めて、それが依存関係を再構築する必要があります。 -iを指定した場合、それらは保存され、2番目のビルド呼び出しははるかに高速になります。

+0

こんにちは、これは正常ですか? の後に 'CGO_ENABLED = 0のビルド-i'私は 'net install:go/install /usr/local/go/pkg/linux_amd64/net.a:許可が拒否されました' –

+0

'go install'はstdlibパッケージを戻したい元の場所:GOROOT。 1.10のために仕事を変えようとしていると思います。それまでは、システムを使用せず、独自のものを使用することで回避することができます(例: 'GOROOT = $ {HOME}/go')。 – Marc

+0

はい、確かにこれは1.10以上で動作します。 'rsc'は最近これについてブログをしていました。 '-i'と同等の機能がデフォルトで使用されます。将来は' pkg'ディレクトリも削除されます。 –

関連する問題