mirror of
https://github.com/golang/go
synced 2024-11-11 20:01:37 -07:00
cmd/go: work out VCS information once per repository
We need VCS status information for each main package we load. If two main packages are under the same VCS repository, we can reuse that information to avoid duplicating work. For instance, the kubernetes holds 51 main packages in its root module, meaning that "go list ./..." repeated the same git calls 51 times. Instead, use a global par.Cache to deduplicate that work. Below are the numbers on kubernetes 5eb584d1cb6917, via "benchcmd -n 8 KubernetesListPackages go list ./...": name old time/op new time/op delta KubernetesListPackages 8.91s ± 0% 3.33s ± 1% -62.61% (p=0.000 n=7+8) name old user-time/op new user-time/op delta KubernetesListPackages 11.2s ± 1% 8.1s ± 2% -27.50% (p=0.000 n=7+8) name old sys-time/op new sys-time/op delta KubernetesListPackages 8.02s ± 0% 1.67s ± 6% -79.21% (p=0.001 n=6+8) name old peak-RSS-bytes new peak-RSS-bytes delta KubernetesListPackages 127MB ± 2% 123MB ± 7% ~ (p=0.328 n=8+8) Fixes #49582. Change-Id: Ib7ef5dc7a35c83a11e209441f5d6f3b8da068259 Reviewed-on: https://go-review.googlesource.com/c/go/+/365394 Trust: Daniel Martí <mvdan@mvdan.cc> Trust: Dominik Honnef <dominik@honnef.co> Run-TryBot: Bryan C. Mills <bcmills@google.com> Reviewed-by: Bryan C. Mills <bcmills@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
0244343088
commit
9678f79414
@ -2203,6 +2203,10 @@ func (p *Package) collectDeps() {
|
||||
}
|
||||
}
|
||||
|
||||
// vcsStatusCache maps repository directories (string)
|
||||
// to their VCS information (vcsStatusError).
|
||||
var vcsStatusCache par.Cache
|
||||
|
||||
// setBuildInfo gathers build information, formats it as a string to be
|
||||
// embedded in the binary, then sets p.Internal.BuildInfo to that string.
|
||||
// setBuildInfo should only be called on a main package with no errors.
|
||||
@ -2365,11 +2369,20 @@ func (p *Package) setBuildInfo() {
|
||||
return
|
||||
}
|
||||
|
||||
st, err := vcsCmd.Status(vcsCmd, repoDir)
|
||||
if err != nil {
|
||||
type vcsStatusError struct {
|
||||
Status vcs.Status
|
||||
Err error
|
||||
}
|
||||
cached := vcsStatusCache.Do(repoDir, func() interface{} {
|
||||
st, err := vcsCmd.Status(vcsCmd, repoDir)
|
||||
return vcsStatusError{st, err}
|
||||
}).(vcsStatusError)
|
||||
if err := cached.Err; err != nil {
|
||||
setVCSError(err)
|
||||
return
|
||||
}
|
||||
st := cached.Status
|
||||
|
||||
if st.Revision != "" {
|
||||
appendSetting(vcsCmd.Cmd+"revision", st.Revision)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ rm $GOBIN/a$GOEXE
|
||||
|
||||
# If there is a repository, but it can't be used for some reason,
|
||||
# there should be an error. It should hint about -buildvcs=false.
|
||||
# Also ensure that multiple errors are collected by "go list -e".
|
||||
cd ..
|
||||
mkdir .git
|
||||
env PATH=$WORK${/}fakebin${:}$oldpath
|
||||
@ -24,6 +25,10 @@ chmod 0755 $WORK/fakebin/git
|
||||
cd a
|
||||
! go install
|
||||
stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$'
|
||||
go list -e -f '{{.ImportPath}}: {{.Error}}' ./...
|
||||
stdout -count=1 '^example\.com/a: error obtaining VCS status'
|
||||
stdout -count=1 '^example\.com/a/library: <nil>'
|
||||
stdout -count=1 '^example\.com/a/othermain: error obtaining VCS status'
|
||||
cd ..
|
||||
env PATH=$oldpath
|
||||
rm .git
|
||||
@ -99,6 +104,14 @@ go version -m $GOBIN/d$GOEXE
|
||||
exec git checkout go.mod
|
||||
rm $GOBIN/d$GOEXE
|
||||
|
||||
# If we're loading multiple main packages,
|
||||
# but they share the same VCS repository,
|
||||
# we only need to execute VCS status commands once.
|
||||
go list -x ./...
|
||||
stdout -count=3 '^example.com'
|
||||
stderr -count=1 '^git status'
|
||||
stderr -count=1 '^git show'
|
||||
|
||||
-- $WORK/fakebin/git --
|
||||
#!/bin/sh
|
||||
exit 1
|
||||
@ -114,6 +127,12 @@ go 1.18
|
||||
-- repo/a/a.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
-- repo/a/library/f.go --
|
||||
package library
|
||||
-- repo/a/othermain/f.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
-- repo/b/go.mod --
|
||||
module example.com/b
|
||||
|
Loading…
Reference in New Issue
Block a user