mirror of
https://github.com/golang/go
synced 2024-10-01 05:38:32 -06:00
cmd/go: cache results of exec.LookPath
This CL package exec.LookPath to internal/cfg.LookPath and adds cache. BenchmarkLookPath-4 24149096 50.48 ns/op 0 B/op 0 allocs/op Fixes #36768 Change-Id: I199a780d1eab9bd5397bb3759bb42191fff716e9 Change-Id: I199a780d1eab9bd5397bb3759bb42191fff716e9 GitHub-Last-Rev: 04cb24b147f2702f01309db754f35a10d9028ced GitHub-Pull-Request: golang/go#61464
This commit is contained in:
parent
3466e57354
commit
d67aa826f4
21
src/cmd/go/internal/cfg/bench_test.go
Normal file
21
src/cmd/go/internal/cfg/bench_test.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/testenv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkLookPath(b *testing.B) {
|
||||||
|
testenv.MustHaveExecPath(b, "go")
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := LookPath("go")
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,6 @@ import (
|
|||||||
"internal/cfg"
|
"internal/cfg"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -161,7 +160,7 @@ func defaultContext() build.Context {
|
|||||||
if ctxt.CgoEnabled {
|
if ctxt.CgoEnabled {
|
||||||
if os.Getenv("CC") == "" {
|
if os.Getenv("CC") == "" {
|
||||||
cc := DefaultCC(ctxt.GOOS, ctxt.GOARCH)
|
cc := DefaultCC(ctxt.GOOS, ctxt.GOARCH)
|
||||||
if _, err := exec.LookPath(cc); err != nil {
|
if _, err := LookPath(cc); err != nil {
|
||||||
ctxt.CgoEnabled = false
|
ctxt.CgoEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
src/cmd/go/internal/cfg/lookpath.go
Normal file
21
src/cmd/go/internal/cfg/lookpath.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/go/internal/par"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
var lookPathCache par.ErrCache[string, string]
|
||||||
|
|
||||||
|
// LookPath wraps exec.LookPath and caches the result
|
||||||
|
// which can be called by multiple Goroutines at the same time.
|
||||||
|
func LookPath(file string) (path string, err error) {
|
||||||
|
return lookPathCache.Do(file,
|
||||||
|
func() (string, error) {
|
||||||
|
return exec.LookPath(file)
|
||||||
|
})
|
||||||
|
}
|
@ -479,7 +479,7 @@ func (g *Generator) exec(words []string) {
|
|||||||
// intends to use the same 'go' as 'go generate' itself.
|
// intends to use the same 'go' as 'go generate' itself.
|
||||||
// Prefer to resolve the binary from GOROOT/bin, and for consistency
|
// Prefer to resolve the binary from GOROOT/bin, and for consistency
|
||||||
// prefer to resolve any other commands there too.
|
// prefer to resolve any other commands there too.
|
||||||
gorootBinPath, err := exec.LookPath(filepath.Join(cfg.GOROOTbin, path))
|
gorootBinPath, err := cfg.LookPath(filepath.Join(cfg.GOROOTbin, path))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
path = gorootBinPath
|
path = gorootBinPath
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"internal/platform"
|
"internal/platform"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
pathpkg "path"
|
pathpkg "path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -2483,7 +2482,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
|||||||
goto omitVCS
|
goto omitVCS
|
||||||
}
|
}
|
||||||
if cfg.BuildBuildvcs == "auto" && vcsCmd != nil && vcsCmd.Cmd != "" {
|
if cfg.BuildBuildvcs == "auto" && vcsCmd != nil && vcsCmd.Cmd != "" {
|
||||||
if _, err := exec.LookPath(vcsCmd.Cmd); err != nil {
|
if _, err := cfg.LookPath(vcsCmd.Cmd); err != nil {
|
||||||
// We fould a repository, but the required VCS tool is not present.
|
// We fould a repository, but the required VCS tool is not present.
|
||||||
// "-buildvcs=auto" means that we should silently drop the VCS metadata.
|
// "-buildvcs=auto" means that we should silently drop the VCS metadata.
|
||||||
goto omitVCS
|
goto omitVCS
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package script
|
package script
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/go/internal/cfg"
|
||||||
"cmd/go/internal/robustio"
|
"cmd/go/internal/robustio"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -824,7 +825,7 @@ func Program(name string, cancel func(*exec.Cmd) error, waitDelay time.Duration)
|
|||||||
},
|
},
|
||||||
func(s *State, args ...string) (WaitFunc, error) {
|
func(s *State, args ...string) (WaitFunc, error) {
|
||||||
lookPathOnce.Do(func() {
|
lookPathOnce.Do(func() {
|
||||||
path, pathErr = exec.LookPath(name)
|
path, pathErr = cfg.LookPath(name)
|
||||||
})
|
})
|
||||||
if pathErr != nil {
|
if pathErr != nil {
|
||||||
return nil, pathErr
|
return nil, pathErr
|
||||||
|
@ -7,10 +7,10 @@ package scripttest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"cmd/go/internal/cfg"
|
||||||
"cmd/go/internal/script"
|
"cmd/go/internal/script"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os/exec"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -137,7 +137,7 @@ func CachedExec() script.Cond {
|
|||||||
return script.CachedCondition(
|
return script.CachedCondition(
|
||||||
"<suffix> names an executable in the test binary's PATH",
|
"<suffix> names an executable in the test binary's PATH",
|
||||||
func(name string) (bool, error) {
|
func(name string) (bool, error) {
|
||||||
_, err := exec.LookPath(name)
|
_, err := cfg.LookPath(name)
|
||||||
return err == nil, nil
|
return err == nil, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -283,7 +282,7 @@ func Exec(gotoolchain string) {
|
|||||||
// Look in PATH for the toolchain before we download one.
|
// Look in PATH for the toolchain before we download one.
|
||||||
// This allows custom toolchains as well as reuse of toolchains
|
// This allows custom toolchains as well as reuse of toolchains
|
||||||
// already installed using go install golang.org/dl/go1.2.3@latest.
|
// already installed using go install golang.org/dl/go1.2.3@latest.
|
||||||
if exe, err := exec.LookPath(gotoolchain); err == nil {
|
if exe, err := cfg.LookPath(gotoolchain); err == nil {
|
||||||
execGoToolchain(gotoolchain, "", exe)
|
execGoToolchain(gotoolchain, "", exe)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
|
|||||||
args = args[2:]
|
args = args[2:]
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := exec.LookPath(v.Cmd)
|
_, err := cfg.LookPath(v.Cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr,
|
fmt.Fprintf(os.Stderr,
|
||||||
"go: missing %s command. See https://golang.org/s/gogetcmd\n",
|
"go: missing %s command. See https://golang.org/s/gogetcmd\n",
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -899,7 +898,7 @@ func FindExecCmd() []string {
|
|||||||
if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
|
if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
|
||||||
return ExecCmd
|
return ExecCmd
|
||||||
}
|
}
|
||||||
path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
|
path, err := cfg.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ExecCmd = []string{path}
|
ExecCmd = []string{path}
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ func (b *Builder) gccToolID(name, language string) (id, exe string, err error) {
|
|||||||
}
|
}
|
||||||
exe = fields[0]
|
exe = fields[0]
|
||||||
if !strings.ContainsAny(exe, `/\`) {
|
if !strings.ContainsAny(exe, `/\`) {
|
||||||
if lp, err := exec.LookPath(exe); err == nil {
|
if lp, err := cfg.LookPath(exe); err == nil {
|
||||||
exe = lp
|
exe = lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2373,11 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([
|
|||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
cmd := exec.Command(cmdline[0], cmdline[1:]...)
|
path, err := cfg.LookPath(cmdline[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cmd := exec.Command(path, cmdline[1:]...)
|
||||||
if cmd.Path != "" {
|
if cmd.Path != "" {
|
||||||
cmd.Args[0] = cmd.Path
|
cmd.Args[0] = cmd.Path
|
||||||
}
|
}
|
||||||
@ -2397,7 +2401,7 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([
|
|||||||
|
|
||||||
cmd.Env = append(cmd.Env, env...)
|
cmd.Env = append(cmd.Env, env...)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := cmd.Run()
|
err = cmd.Run()
|
||||||
if a != nil && a.json != nil {
|
if a != nil && a.json != nil {
|
||||||
aj := a.json
|
aj := a.json
|
||||||
aj.Cmd = append(aj.Cmd, joinUnambiguously(cmdline))
|
aj.Cmd = append(aj.Cmd, joinUnambiguously(cmdline))
|
||||||
@ -3017,7 +3021,7 @@ func (b *Builder) gccCompilerID(compiler string) (id cache.ActionID, ok bool) {
|
|||||||
//
|
//
|
||||||
// Otherwise, we compute a new validation description
|
// Otherwise, we compute a new validation description
|
||||||
// and compiler id (below).
|
// and compiler id (below).
|
||||||
exe, err := exec.LookPath(compiler)
|
exe, err := cfg.LookPath(compiler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cache.ActionID{}, false
|
return cache.ActionID{}, false
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func init() {
|
|||||||
if GccgoName == "" {
|
if GccgoName == "" {
|
||||||
GccgoName = "gccgo"
|
GccgoName = "gccgo"
|
||||||
}
|
}
|
||||||
GccgoBin, gccgoErr = exec.LookPath(GccgoName)
|
GccgoBin, gccgoErr = cfg.LookPath(GccgoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gccgoToolchain) compiler() string {
|
func (gccgoToolchain) compiler() string {
|
||||||
|
Loading…
Reference in New Issue
Block a user