mirror of https://github.com/golang/go.git
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.
|
// run through go run and go test respectively.
|
||||||
// -pgo file
|
// -pgo file
|
||||||
// specify the file path of a profile for profile-guided optimization (PGO).
|
// 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.
|
// Special name "off" turns off PGO.
|
||||||
// -pkgdir dir
|
// -pkgdir dir
|
||||||
// install and load all packages from dir instead of the usual locations.
|
// 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
|
// 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).
|
// package path or pattern ending in '.go' (see golang.org/issue/34653).
|
||||||
if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
|
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).
|
// their dependencies).
|
||||||
setToolFlags(pkgs...)
|
setToolFlags(pkgs...)
|
||||||
|
|
||||||
|
setPGOProfilePath(pkgs)
|
||||||
|
|
||||||
return 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
|
// CheckPackageErrors prints errors encountered loading pkgs and their
|
||||||
// dependencies, then exits with a non-zero status if any errors were found.
|
// dependencies, then exits with a non-zero status if any errors were found.
|
||||||
func CheckPackageErrors(pkgs []*Package) {
|
func CheckPackageErrors(pkgs []*Package) {
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ and test commands:
|
||||||
run through go run and go test respectively.
|
run through go run and go test respectively.
|
||||||
-pgo file
|
-pgo file
|
||||||
specify the file path of a profile for profile-guided optimization (PGO).
|
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.
|
Special name "off" turns off PGO.
|
||||||
-pkgdir dir
|
-pkgdir dir
|
||||||
install and load all packages from dir instead of the usual locations.
|
install and load all packages from dir instead of the usual locations.
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,6 @@ func BuildInit() {
|
||||||
if cfg.BuildRace && cfg.BuildCoverMode != "atomic" {
|
if cfg.BuildRace && cfg.BuildCoverMode != "atomic" {
|
||||||
base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, cfg.BuildCoverMode)
|
base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, cfg.BuildCoverMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
setPGOProfilePath()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation
|
// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation
|
||||||
|
|
@ -442,21 +440,3 @@ func compilerRequiredAsanVersion() error {
|
||||||
}
|
}
|
||||||
return nil
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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