2017-12-08 2 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에 바인딩을 사용하지 않는

여부는 어떤 관련성이없는 것 같다 I '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을 지정하면 파일이 저장되고 두 번째 빌드 호출이 훨씬 빠릅니다.

+0

흠,이게 정상인가요? 이후'CGO_ENABLED = 0 빌드'-i'설치 net : open /usr/local/go/pkg/linux_amd64/net.a : permission denied' –

+0

'go install'은 stdlib 패키지를 다시 넣기를 원합니다. 원래 위치 :'GOROOT'. 나는 그것을 바꾸기 위해 일이 끝났다고 믿는다. 어쩌면 1.10. 그때까지는 시스템을 사용하지 않고 자신 만의 시스템을 사용하지 않을 수 있습니다 (예 :'GOROOT = $ {HOME}/go'). – Marc

+0

예 1.10 이상에서는이 작업이 가능합니다. 'rsc'가 최근에 블로깅을하고있었습니다. '-i'와 동등한 기능이 기본적으로 사용될 것이며, 미래에는'pkg' 디렉토리도 사라질 것입니다. –

관련 문제