mirror of
https://github.com/golang/go
synced 2024-09-29 12:24:31 -06:00
cmd/go: add PGO auto mode
Add "auto" mode for the -pgo build flag. When -pgo=auto is specified, if there is a default.pgo file in the directory of the main package, it will be selected and used for the build. Currently it requires exactly one main package when -pgo=auto is specified. (We'll support multiple main packages in the future.) Also apply to other build-related subcommands, "go install", "go run", "go test", and "go list". For #55022. Change-Id: Iab7974ab8932daf0e83506de505e044a8e412466 Reviewed-on: https://go-review.googlesource.com/c/go/+/438737 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> Run-TryBot: Bryan Mills <bcmills@google.com>
This commit is contained in:
parent
17de9e2d18
commit
32851587d1
@ -202,6 +202,8 @@
|
||||
// run through go run and go test respectively.
|
||||
// -pgo file
|
||||
// specify the file path of a profile for profile-guided optimization (PGO).
|
||||
// Special name "auto" lets the go command select a file named
|
||||
// "default.pgo" in the main package's directory if that file exists.
|
||||
// Special name "off" turns off PGO.
|
||||
// -pkgdir dir
|
||||
// install and load all packages from dir instead of the usual locations.
|
||||
|
@ -2807,7 +2807,9 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
|
||||
// We need to test whether the path is an actual Go file and not a
|
||||
// package path or pattern ending in '.go' (see golang.org/issue/34653).
|
||||
if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
|
||||
return []*Package{GoFilesPackage(ctx, opts, patterns)}
|
||||
pkgs := []*Package{GoFilesPackage(ctx, opts, patterns)}
|
||||
setPGOProfilePath(pkgs)
|
||||
return pkgs
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2886,9 +2888,60 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
|
||||
// their dependencies).
|
||||
setToolFlags(pkgs...)
|
||||
|
||||
setPGOProfilePath(pkgs)
|
||||
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// setPGOProfilePath sets cfg.BuildPGOFile to the PGO profile path.
|
||||
// In -pgo=auto mode, it finds the default PGO profile.
|
||||
func setPGOProfilePath(pkgs []*Package) {
|
||||
switch cfg.BuildPGO {
|
||||
case "":
|
||||
fallthrough // default to "off"
|
||||
case "off":
|
||||
return
|
||||
|
||||
case "auto":
|
||||
// Locate PGO profile from the main package.
|
||||
|
||||
setError := func(p *Package) {
|
||||
if p.Error == nil {
|
||||
p.Error = &PackageError{Err: errors.New("-pgo=auto requires exactly one main package")}
|
||||
}
|
||||
}
|
||||
|
||||
var mainpkg *Package
|
||||
for _, p := range pkgs {
|
||||
if p.Name == "main" {
|
||||
if mainpkg != nil {
|
||||
setError(p)
|
||||
setError(mainpkg)
|
||||
continue
|
||||
}
|
||||
mainpkg = p
|
||||
}
|
||||
}
|
||||
if mainpkg == nil {
|
||||
// No main package, no default.pgo to look for.
|
||||
return
|
||||
}
|
||||
file := filepath.Join(mainpkg.Dir, "default.pgo")
|
||||
if fi, err := os.Stat(file); err == nil && !fi.IsDir() {
|
||||
cfg.BuildPGOFile = file
|
||||
}
|
||||
|
||||
default:
|
||||
// Profile specified from the command line.
|
||||
// Make it absolute path, as the compiler runs on various directories.
|
||||
if p, err := filepath.Abs(cfg.BuildPGO); err != nil {
|
||||
base.Fatalf("fail to get absolute path of PGO file %s: %v", cfg.BuildPGO, err)
|
||||
} else {
|
||||
cfg.BuildPGOFile = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckPackageErrors prints errors encountered loading pkgs and their
|
||||
// dependencies, then exits with a non-zero status if any errors were found.
|
||||
func CheckPackageErrors(pkgs []*Package) {
|
||||
|
@ -159,6 +159,8 @@ and test commands:
|
||||
run through go run and go test respectively.
|
||||
-pgo file
|
||||
specify the file path of a profile for profile-guided optimization (PGO).
|
||||
Special name "auto" lets the go command select a file named
|
||||
"default.pgo" in the main package's directory if that file exists.
|
||||
Special name "off" turns off PGO.
|
||||
-pkgdir dir
|
||||
install and load all packages from dir instead of the usual locations.
|
||||
|
@ -84,8 +84,6 @@ func BuildInit() {
|
||||
if cfg.BuildRace && cfg.BuildCoverMode != "atomic" {
|
||||
base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, cfg.BuildCoverMode)
|
||||
}
|
||||
|
||||
setPGOProfilePath()
|
||||
}
|
||||
|
||||
// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation
|
||||
@ -442,21 +440,3 @@ func compilerRequiredAsanVersion() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setPGOProfilePath() {
|
||||
switch cfg.BuildPGO {
|
||||
case "":
|
||||
fallthrough // default to "auto"
|
||||
case "off":
|
||||
// Nothing to do.
|
||||
case "auto":
|
||||
base.Fatalf("-pgo=auto is not implemented")
|
||||
default:
|
||||
// make it absolute path, as the compiler runs on various directories.
|
||||
if p, err := filepath.Abs(cfg.BuildPGO); err != nil {
|
||||
base.Fatalf("fail to get absolute path of PGO file %s: %v", cfg.BuildPGO, err)
|
||||
} else {
|
||||
cfg.BuildPGOFile = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
src/cmd/go/testdata/script/build_pgo_auto.txt
vendored
Normal file
69
src/cmd/go/testdata/script/build_pgo_auto.txt
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
# Test go build -pgo=auto flag.
|
||||
|
||||
# use default.pgo for a single main package
|
||||
go build -n -pgo=auto ./a/a1
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
|
||||
|
||||
# check that pgo applied to dependencies
|
||||
stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
|
||||
|
||||
# use default.pgo for ... with a single main package
|
||||
go build -n -pgo=auto ./a/...
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
|
||||
|
||||
# error with multiple packages
|
||||
! go build -n -pgo=auto ./b/...
|
||||
stderr '-pgo=auto requires exactly one main package'
|
||||
|
||||
# build succeeds without PGO when default.pgo file is absent
|
||||
go build -n -pgo=auto -o nopgo.exe ./nopgo
|
||||
stderr 'compile.*nopgo.go'
|
||||
! stderr '-pgoprofile'
|
||||
|
||||
# other build-related commands
|
||||
go install -n -pgo=auto ./a/a1
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
|
||||
|
||||
go run -n -pgo=auto ./a/a1
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
|
||||
|
||||
go test -n -pgo=auto ./a/a1
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go.*a1_test.go'
|
||||
stderr 'compile.*-pgoprofile=.*default\.pgo.*external_test.go'
|
||||
|
||||
# go list commands should succeed as usual
|
||||
go list -pgo=auto ./a/a1
|
||||
|
||||
go list -test -pgo=auto ./a/a1
|
||||
|
||||
go list -deps -pgo=auto ./a/a1
|
||||
|
||||
-- go.mod --
|
||||
module test
|
||||
go 1.20
|
||||
-- a/a1/a1.go --
|
||||
package main
|
||||
import _ "test/dep"
|
||||
func main() {}
|
||||
-- a/a1/a1_test.go --
|
||||
package main
|
||||
import "testing"
|
||||
func TestA(*testing.T) {}
|
||||
-- a/a1/external_test.go --
|
||||
package main_test
|
||||
import "testing"
|
||||
func TestExternal(*testing.T) {}
|
||||
-- a/a1/default.pgo --
|
||||
-- b/b1/b1.go --
|
||||
package main
|
||||
func main() {}
|
||||
-- b/b1/default.pgo --
|
||||
-- b/b2/b2.go --
|
||||
package main
|
||||
func main() {}
|
||||
-- b/b2/default.pgo --
|
||||
-- nopgo/nopgo.go --
|
||||
package main
|
||||
func main() {}
|
||||
-- dep/dep.go --
|
||||
package dep
|
Loading…
Reference in New Issue
Block a user