GOPATH보다 Go 모듈이 빠른 이유

7574 단어 go
Go 모듈을 사용하여 의존항을 다운로드하는 것은 GOPATH 기반의 의존항을 사용하는 것보다 훨씬 빠르다.이 글의 새로운 의존항 다운로드 실험은 GOPATH 모드에서 9분 33.845초, 모듈 모드에서 10.185초 걸렸다.이 글은 원인을 설명했다.중요한 차이점은 모듈이 깊이 있는 저장소 복제를 피하고 모듈 에이전트를 사용할 수 있다는 것이다.

For an introduction to Go modules, see https://blog.golang.org/using-go-modules.

GOPATH의 의존항 관리를 바탕으로 각 의존항을 GOPATH/src에 다운로드하여 이 과정에서 버전 제어 저장소를 깊이 있게 복제합니다.
따라서 만약에 GOPATH 모드에 있고 프로젝트는 A에 의존하고 A는 B에 의존하고 B는 C에 의존한다면 go 명령은 git clone의 세 개의 저장소를 모두 사용한다.
Go 모듈을 사용할 때 종속 항목을 다운로드하는 데 두 가지 작업이 필요합니다.
  • 의존항의 원본 코드입니다.
  • 의존항의 go.mod 파일입니다.
  • go.mod 파일은 필요한 모든 의존 항목의 버전을 확인하는 데 사용됩니다.go 명령이 모든 의존 항목에서 go.mod 파일을 수집하면 프로젝트가 의존 항목의 어느 버전을 필요로 하는지 확인할 수 있습니다.
    예를 들어 모듈 A와 B에 직접 의존하고 모듈 A가 모듈 B의 v1.2.0에 의존한다면 모듈은 적어도 B v1.2.0에 의존해야 합니다.같은 생각은 직접적이든 간접적이든 당신이 의존하는 모든 모듈에도 적용된다.

    Side note: notice that if a new version of module A or B is released, that doesn't change the minimum version of B you must depend on. That requirement is stable over time.


    모듈 에이전트


    모듈 에이전트는 Go 모듈의 속도가 이렇게 빠른 중요한 원인입니다.모듈 에이전트는 각 모듈 의존항에서 원본 코드와 go.mod 파일의 두 가지 구성 요소를 이해합니다.이러한 이해는 두 가지 서로 다른 최적화를 초래했다.
  • 소스 코드는 깊이 VCS 클론이 아닌 zip 파일로 배포할 수 있습니다.단일 zip 파일을 다운로드하는 것이 전체 VCS 복제보다 훨씬 빨라서 모듈 다운로드가 GOPATH보다 효율적이다.
  • 나머지 원본 코드를 가져오지 않고 go.mod 파일을 다운로드할 수 있습니다.이것은 모듈 에이전트를 사용하는 것이 에이전트를 사용하지 않는 것보다 더 효과적이다.
  • 최적화 #1은 go 명령이 의존항을 다운로드할 때 GOPATH보다 다운로드 내용이 적다는 것을 의미한다.git clone 명령은 전체 go을 실행할 필요가 없고, 필요한 모듈 버전 원본 코드를 포함하는 zip 파일을 다운로드합니다.
    프록시가 없는 모듈을 사용하는 경우 go 명령은 가능한 한 얕은 클론을 실행합니다.전체 저장소 기록이 아닌 커밋을 한 번만 읽어들이기 때문에 얕은 클론은 깊이 클론보다 훨씬 빠릅니다.
    그 결과 모듈을 사용할 때 GOPATH보다 다운로드 내용이 적었다.
    최적화 #2, go.mod 파일을 이해하면 더욱 미묘합니다.
    모듈은 모듈 그림에서 가져오기 그림에 있는 것을 의미하지 않습니다.모듈 그림은 go.mod 파일, 모든 의존항의 go.mod 파일, 모든 의존항의 go.mod 파일 등에 포함된 전체 모듈 목록을 포함한다.가져오기 그림은 항목이 가져온 모든 패키지와 이 패키지가 가져온 패키지 등을 포함합니다.의존하는 모듈은 컴파일 항목이 필요하지 않은 패키지를 포함할 수 있습니다.
    예를 들어, Postgres, MySQL 및 MongoDB를 지원하는 데이터베이스 도우미에 의존한다고 가정합니다.helper는 지원되는 모든 데이터베이스에 단독 패키지를 제공합니다. 모든 패키지는 제3자 모듈/패키지에 의존하여 이 데이터베이스와 통신합니다.프로젝트는 Helper의 Postgres 패키지만 사용하기 때문에 MySQL이나 MongoDB 패키지로 프로젝트를 구축할 필요가 없습니다.또한 MySQL이나 MongoDB 모듈의 원본 코드로 프로젝트를 컴파일할 필요가 없습니다. 가져오기 그림에 없기 때문입니다!

    하지만 이 모듈에는 go.mod 파일이 필요합니다.모듈이 모듈 그림에 있다면, 사용할 모든 의존항의 최저 버전을 계산할 때, 반드시 그것을 고려해야 합니다.
    여기는 모듈 에이전트의 구출지입니다.모듈 에이전트는 원본 코드가 필요 없이 주어진 모듈에 go.mod 파일을 제공할 수 있습니다.프록시를 사용하지 않으면, 전체 리포 (소스 코드와 모든 코드) 를 복제해야만 go.mod 파일을 얻을 수 있습니다. 코드가 영원히 컴파일되지 않을 것을 알고 있기 때문입니다.주의해야 할 것은 위에서 말한 바와 같이 모듈 모드에서의 go 명령은 가능한 한 얕은 복제를 진행한다.GOPATH 모드에 있을 때, go 명령은 가져오기 그림의 의존 항목만 다운로드합니다.따라서 모듈 에이전트를 사용하지 않는 것에 비해 이런 특정한 에이전트 최적화는 성능만 향상시킬 뿐이다.Lazy module loading(Go 1.16용으로 계획됨) go.mod 명령에 필요한 go 파일의 수를 줄여 모듈의 속도를 더욱 높일 수 있습니다.

    결과


    상술한 최적화는 (1) 다운로드할 것이 더 작고 (2) 다운로드할 것이 더 적다는 것을 의미한다.
    한 마디로 하면 프록시를 사용하지 않는 것보다 프록시를 사용할 때 새 모듈의 다운로드 속도가 5배 정도 빠르다.GOPATH에 비해 에이전트가 있는 모듈을 사용하면 50배 이상 빠릅니다.

    It's theoretically possible for modules to be slower because you need to download each version of a dependency separately, rather than only having a single version of the dependency in your system. In practice, modules are much faster and the cache requires less space on disk, especially when you factor in standard GOPATH+vendoring patterns.


    해보다


    이러한 최적화된 실제 효과를 보려면 선택한 의존항을 사용하여 다음 명령을 시도하십시오.Starting with Go 1.13, 기본 모듈 에이전트는 proxy.golang.org입니다. Go 1.13 이상의 버전을 사용하고 있고 모듈을 사용하고 GOPROXY을 조정하지 않았다면 이러한 장점을 얻었습니다.

    I used Cloud Shell to run these tests. Your results may vary depending on the machine you're using, the Go version you're using, your network speed, the dependency you test with, and other factors.


  • 우선 정상적인 GOPATH 내용을 삭제하지 않도록 임시 빈 GOPATH을 만들어서 테스트를 진행합니다.
    $ mkdir /tmp/tmp.GOPATH
    $ export GOPATH=/tmp/tmp.GOPATH
    $ go env GOPATH # Just to confirm.
    /tmp/tmp.GOPATH
    

  • 현재 의존 항목을 GOPATH 모드로 다운로드해 보십시오.이 명령들은 cloud.google.com/go/storage을 사용하지만, 의존 항목을 사용할 수 있습니다.
    # Force GOPATH mode. Be sure the current directory
    # doesn't have a go.mod.
    $ export GO111MODULES=off
    $ time go get cloud.google.com/go/storage
    real    9m33.845s
    user    4m1.197s
    sys     0m18.079s
    

    You can find the cloud.google.com/go/storage go.mod file on GitHub.



  • 다음으로 Go 모듈을 사용해 보십시오.테스트할 새 모듈 만들기:
    $ mkdir proxy-testing
    $ cd proxy-testing
    $ unset GO111MODULES # Back to the default.
    $ go mod init example.com/proxy-testing
    

  • 이제 에이전트가 없는 의존 항목을 다운로드해 보십시오.
    $ go clean -modcache # Careful!
    $ go env -w GOPROXY=direct # direct means go directly to the source.
    $ go env GOPROXY
    direct
    $ time go get cloud.google.com/go/storage
    go: finding cloud.google.com/go/storage v1.10.0
    ...
    
    real    2m6.396s
    user    1m51.447s
    sys     0m18.311s
    

  • 이제 프록시가 활성화된 상태에서 시도(GOPROXY을 기본값으로 재설정):
    $ go env -w GOPROXY=
    $ go env GOPROXY
    https://proxy.golang.org,direct
    $ go clean -modcache # Careful!
    $ go mod tidy # To start from the same state as before.
    $ time go get cloud.google.com/go/storage
    go: finding cloud.google.com/go/storage v1.10.0
    ...
    
    real    0m10.185s
    user    0m9.610s
    sys     0m1.961s
    

  • 다운로드 cloud.google.com/go/storage 필요:GOPATH 모드에서의
  • 9m33.845s,
  • 2m6.396s는 에이전트가 없는 모듈을 사용하고
  • 10.185s는 프록시가 있는 모듈을 사용합니다(기본값).
  • 만약 기계에서 이런 테스트를 운행한다면 결과는 다소 달라질 것이다.그러나 모듈의 속도는 GOPATH보다 현저히 빠르다. 특히 기본 프록시를 사용할 때이다.

    좋은 웹페이지 즐겨찾기