sweet: rebuild cmd/compile and cmd/link for go-build benchmark
go-build is a subtly strange benchmark. For every other benchmark, sweet
builds the benchmarked program in set up, using Config.BuildEnv.
go-build does not do that because the benchmarked programs (cmd/compile,
cmd/link, and (to a lesser degree) cmd/go) are conveniently prebuilt in
GOROOT.
But this breaks the intuition that BuildEnv can control build flags for
the benchmarked program, particularly for sweet run -pgo, where sweet
itself expects a PGO flag in BuildEnv to impact the benchmarked program.
Adjust go-build to follow these standards by copying GOROOT for each
config and running `go install cmd/compile cmd/link` in the copied
GOROOT, allowing BuildEnv to take effect.
This fixes the general case for PGO, though it could use more work as
really cmd/compile and cmd/link should receive _different_ PGO profiles.
We also run the dummy build with the ExecEnv (matching how the actual
benchmark will run) to avoid passing -pgo to those builds.
For golang/go#55022.
Change-Id: I36e4486c79ee4200c2e10ccba913d559187bdad2
Reviewed-on: https://go-review.googlesource.com/c/benchmarks/+/444895
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/sweet/harnesses/go-build.go b/sweet/harnesses/go-build.go
index a55113e..3b3e278 100644
--- a/sweet/harnesses/go-build.go
+++ b/sweet/harnesses/go-build.go
@@ -10,6 +10,7 @@
"path/filepath"
"golang.org/x/benchmarks/sweet/common"
+ "golang.org/x/benchmarks/sweet/common/fileutil"
"golang.org/x/benchmarks/sweet/common/log"
)
@@ -72,12 +73,30 @@
return nil
}
-func (h GoBuild) Build(cfg *common.Config, bcfg *common.BuildConfig) error {
+func (h GoBuild) Build(pcfg *common.Config, bcfg *common.BuildConfig) error {
+ // Local copy of config for updating GOROOT.
+ cfg := pcfg.Copy()
+
benchmarks := buildBenchmarks
if bcfg.Short {
// Do only the pkgsite benchmark.
benchmarks = []*buildBenchmark{buildBenchmarks[2]}
}
+
+ // cfg.GoRoot is our source toolchain. We need to rebuild cmd/compile
+ // and cmd/link with cfg.BuildEnv to apply any configured build options
+ // (e.g., PGO).
+ //
+ // Do so by `go install`ing them into a copied GOROOT.
+ goroot := filepath.Join(bcfg.BinDir, "goroot")
+ if err := fileutil.CopyDir(goroot, cfg.GoRoot, nil); err != nil {
+ return fmt.Errorf("error copying GOROOT: %v", err)
+ }
+ cfg.GoRoot = goroot
+ if err := cfg.GoTool().Do("install", "cmd/compile", "cmd/link"); err != nil {
+ return fmt.Errorf("error building cmd/compile and cmd/link: %v", err)
+ }
+
for _, bench := range benchmarks {
// Generate a symlink to the repository and put it in bin.
// It's not a binary, but it's the only place we can put it
@@ -89,9 +108,14 @@
}
// Build the benchmark once, pulling in any requisite packages.
+ //
+ // Run the go tool with ExecEnv, as that is what we will use
+ // when benchmarking.
pkgPath := filepath.Join(bcfg.BinDir, bench.name, bench.pkg)
dummyBin := filepath.Join(bcfg.BinDir, "dummy")
- if err := cfg.GoTool().BuildPath(pkgPath, dummyBin); err != nil {
+ goTool := cfg.GoTool()
+ goTool.Env = cfg.ExecEnv.MustSet("GOROOT=" + cfg.GoRoot)
+ if err := goTool.BuildPath(pkgPath, dummyBin); err != nil {
return fmt.Errorf("error building %s %s: %w", bench.name, bench.pkg, err)
}
}
@@ -102,7 +126,11 @@
return nil
}
-func (h GoBuild) Run(cfg *common.Config, rcfg *common.RunConfig) error {
+func (h GoBuild) Run(pcfg *common.Config, rcfg *common.RunConfig) error {
+ // Local copy of config for updating GOROOT.
+ cfg := pcfg.Copy()
+ cfg.GoRoot = filepath.Join(rcfg.BinDir, "goroot") // see Build, above.
+
benchmarks := buildBenchmarks
if rcfg.Short {
// Do only the pkgsite benchmark.