mirror of https://github.com/golang/go.git
cmd/go/internal/work: use par.Cache to cache tool IDs.
The tool IDs can be calculated once and reused across multiple threads. This is a small optimization that helps optimize system resources. On a normal Windows machine with 12 virtual CPUs, the time to build a hello world program is reduced from over 1 second, with spikes of 2 seconds, to a consistent 0.7 seconds. Updates #71981. Change-Id: I85f4a19f8ad4230afa32213780c761b7eb22fa29 Reviewed-on: https://go-review.googlesource.com/c/go/+/653715 Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
039b3ebeba
commit
f4750a6cfb
|
|
@ -10,6 +10,7 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"cmd/internal/cov/covcmd"
|
||||
"cmd/internal/par"
|
||||
"container/heap"
|
||||
"context"
|
||||
"debug/elf"
|
||||
|
|
@ -56,9 +57,10 @@ type Builder struct {
|
|||
readySema chan bool
|
||||
ready actionQueue
|
||||
|
||||
id sync.Mutex
|
||||
toolIDCache map[string]string // tool name -> tool ID
|
||||
buildIDCache map[string]string // file name -> build ID
|
||||
id sync.Mutex
|
||||
toolIDCache par.Cache[string, string] // tool name -> tool ID
|
||||
gccToolIDCache map[string]string // tool name -> tool ID
|
||||
buildIDCache map[string]string // file name -> build ID
|
||||
}
|
||||
|
||||
// NOTE: Much of Action would not need to be exported if not for test.
|
||||
|
|
@ -268,7 +270,7 @@ func NewBuilder(workDir string) *Builder {
|
|||
b := new(Builder)
|
||||
|
||||
b.actionCache = make(map[cacheKey]*Action)
|
||||
b.toolIDCache = make(map[string]string)
|
||||
b.gccToolIDCache = make(map[string]string)
|
||||
b.buildIDCache = make(map[string]string)
|
||||
|
||||
printWorkDir := false
|
||||
|
|
|
|||
|
|
@ -144,55 +144,42 @@ func contentID(buildID string) string {
|
|||
// build setups agree on details like $GOROOT and file name paths, but at least the
|
||||
// tool IDs do not make it impossible.)
|
||||
func (b *Builder) toolID(name string) string {
|
||||
b.id.Lock()
|
||||
id := b.toolIDCache[name]
|
||||
b.id.Unlock()
|
||||
return b.toolIDCache.Do(name, func() string {
|
||||
path := base.Tool(name)
|
||||
desc := "go tool " + name
|
||||
|
||||
if id != "" {
|
||||
return id
|
||||
}
|
||||
|
||||
path := base.Tool(name)
|
||||
desc := "go tool " + name
|
||||
|
||||
// Special case: undocumented -vettool overrides usual vet,
|
||||
// for testing vet or supplying an alternative analysis tool.
|
||||
if name == "vet" && VetTool != "" {
|
||||
path = VetTool
|
||||
desc = VetTool
|
||||
}
|
||||
|
||||
cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
|
||||
cmd := exec.Command(cmdline[0], cmdline[1:]...)
|
||||
var stdout, stderr strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
if stderr.Len() > 0 {
|
||||
os.Stderr.WriteString(stderr.String())
|
||||
// Special case: undocumented -vettool overrides usual vet,
|
||||
// for testing vet or supplying an alternative analysis tool.
|
||||
if name == "vet" && VetTool != "" {
|
||||
path = VetTool
|
||||
desc = VetTool
|
||||
}
|
||||
base.Fatalf("go: error obtaining buildID for %s: %v", desc, err)
|
||||
}
|
||||
|
||||
line := stdout.String()
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") {
|
||||
base.Fatalf("go: parsing buildID from %s -V=full: unexpected output:\n\t%s", desc, line)
|
||||
}
|
||||
if f[2] == "devel" {
|
||||
// On the development branch, use the content ID part of the build ID.
|
||||
id = contentID(f[len(f)-1])
|
||||
} else {
|
||||
cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
|
||||
cmd := exec.Command(cmdline[0], cmdline[1:]...)
|
||||
var stdout, stderr strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
if stderr.Len() > 0 {
|
||||
os.Stderr.WriteString(stderr.String())
|
||||
}
|
||||
base.Fatalf("go: error obtaining buildID for %s: %v", desc, err)
|
||||
}
|
||||
|
||||
line := stdout.String()
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") {
|
||||
base.Fatalf("go: parsing buildID from %s -V=full: unexpected output:\n\t%s", desc, line)
|
||||
}
|
||||
if f[2] == "devel" {
|
||||
// On the development branch, use the content ID part of the build ID.
|
||||
return contentID(f[len(f)-1])
|
||||
}
|
||||
// For a release, the output is like: "compile version go1.9.1 X:framepointer".
|
||||
// Use the whole line.
|
||||
id = strings.TrimSpace(line)
|
||||
}
|
||||
|
||||
b.id.Lock()
|
||||
b.toolIDCache[name] = id
|
||||
b.id.Unlock()
|
||||
|
||||
return id
|
||||
return strings.TrimSpace(line)
|
||||
})
|
||||
}
|
||||
|
||||
// gccToolID returns the unique ID to use for a tool that is invoked
|
||||
|
|
@ -216,10 +203,11 @@ func (b *Builder) toolID(name string) string {
|
|||
// to detect changes in the underlying compiler. The returned exe can be empty,
|
||||
// which means to rely only on the id.
|
||||
func (b *Builder) gccToolID(name, language string) (id, exe string, err error) {
|
||||
//TODO: Use par.Cache instead of a mutex and a map. See Builder.toolID.
|
||||
key := name + "." + language
|
||||
b.id.Lock()
|
||||
id = b.toolIDCache[key]
|
||||
exe = b.toolIDCache[key+".exe"]
|
||||
id = b.gccToolIDCache[key]
|
||||
exe = b.gccToolIDCache[key+".exe"]
|
||||
b.id.Unlock()
|
||||
|
||||
if id != "" {
|
||||
|
|
@ -309,8 +297,8 @@ func (b *Builder) gccToolID(name, language string) (id, exe string, err error) {
|
|||
}
|
||||
|
||||
b.id.Lock()
|
||||
b.toolIDCache[key] = id
|
||||
b.toolIDCache[key+".exe"] = exe
|
||||
b.gccToolIDCache[key] = id
|
||||
b.gccToolIDCache[key+".exe"] = exe
|
||||
b.id.Unlock()
|
||||
|
||||
return id, exe, nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue