Skip to content

Commit 9e5447a

Browse files
mknyszekgopherbot
authored andcommitted
cmd/bench: add -pgo flag
This change adds a flag to cmd/bench to do a few runs to collect profiles and feed that back into the build before doing measured benchmark runs. This mode is only supported in Sweet to begin with. Change-Id: I483ca5d5385b341dee4038641e16e02f2ce3493d Reviewed-on: https://go-review.googlesource.com/c/benchmarks/+/594776 Auto-Submit: Michael Knyszek <[email protected]> Reviewed-by: Michael Pratt <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1dfa65a commit 9e5447a

File tree

4 files changed

+62
-24
lines changed

4 files changed

+62
-24
lines changed

cmd/bench/bent.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ func removeAllIncludingReadonly(dir string) error {
6363
return os.RemoveAll(dir)
6464
}
6565

66-
func bent(tcs []*toolchain) (err error) {
66+
func bent(tcs []*toolchain, pgo bool) (err error) {
67+
if pgo {
68+
log.Printf("Skipping bent benchmarks (PGO not supported)")
69+
return nil
70+
}
6771
dir, err := os.MkdirTemp("", "bent")
6872
if err != nil {
6973
return fmt.Errorf("error creating temporary directory: %w", err)

cmd/bench/gotest.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import (
1010
"path/filepath"
1111
)
1212

13-
func goTest(tcs []*toolchain) error {
13+
func goTest(tcs []*toolchain, pgo bool) error {
14+
if pgo {
15+
log.Printf("Skipping Go test benchmarks (PGO not supported)")
16+
return nil
17+
}
1418
for _, tc := range tcs {
1519
log.Printf("Running Go test benchmarks for %s", tc.Name)
1620
fmt.Printf("toolchain: %s\n", tc.Name)

cmd/bench/main.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
var (
2626
wait = flag.Bool("wait", true, "wait for system idle before starting benchmarking")
27+
pgo = flag.Bool("pgo", false, "run the benchmarks to collect profiles and rebuild them with PGO enabled before measuring")
2728
gorootExperiment = flag.String("goroot", "", "GOROOT to test (default $GOROOT or 'go env GOROOT')")
2829
gorootBaseline = flag.String("goroot-baseline", "", "baseline GOROOT to test against (optional) (default $BENCH_BASELINE_GOROOT)")
2930
branch = flag.String("branch", "", "branch of the commits we're testing against (default $BENCH_BRANCH or unknown)")
@@ -64,16 +65,17 @@ func toolchainFromGOROOT(name, goroot string) *toolchain {
6465
}
6566
}
6667

67-
func run(tcs []*toolchain) error {
68+
func run(tcs []*toolchain, pgo bool) error {
6869
// Because each of the functions below is responsible for running
6970
// benchmarks under each toolchain itself, it is also responsible
7071
// for ensuring that the benchmark tag "toolchain" is printed.
7172
pass := true
72-
if err := goTest(tcs); err != nil {
73+
74+
if err := goTest(tcs, pgo); err != nil {
7375
pass = false
7476
log.Printf("Error running Go tests: %v", err)
7577
}
76-
if err := bent(tcs); err != nil {
78+
if err := bent(tcs, pgo); err != nil {
7779
pass = false
7880
log.Printf("Error running bent: %v", err)
7981
}
@@ -93,7 +95,7 @@ func run(tcs []*toolchain) error {
9395
return fmt.Errorf("failed to clean Go cache: %w", err)
9496
}
9597
}
96-
if err := sweet(tcs); err != nil {
98+
if err := sweet(tcs, pgo); err != nil {
9799
pass = false
98100
log.Printf("Error running sweet: %v", err)
99101
}
@@ -189,7 +191,7 @@ func main() {
189191
return
190192
}
191193
// Run benchmarks against the toolchains.
192-
if err := run(toolchains); err != nil {
194+
if err := run(toolchains, *pgo); err != nil {
193195
log.Print("FAIL")
194196
os.Exit(1)
195197
}

cmd/bench/sweet.go

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func writeSweetConfiguration(filename string, tcs []*toolchain) error {
3939
return nil
4040
}
4141

42-
func sweet(tcs []*toolchain) (err error) {
42+
func sweet(tcs []*toolchain, pgo bool) (err error) {
4343
tmpDir, err := os.MkdirTemp("", "go-sweet")
4444
if err != nil {
4545
return fmt.Errorf("error creating temporary directory: %w", err)
@@ -103,16 +103,20 @@ func sweet(tcs []*toolchain) (err error) {
103103
// Finally we can actually run the benchmarks.
104104
resultsDir := filepath.Join(tmpDir, "results")
105105
workDir := filepath.Join(tmpDir, "work")
106-
cmd = exec.Command(
107-
sweetBin, "run",
106+
sweetRunArgs := []string{
107+
"run",
108108
"-run", "default",
109109
"-count", "10",
110110
"-bench-dir", filepath.Join(sweetRoot, "benchmarks"),
111111
"-cache", assetsCacheDir,
112112
"-work-dir", workDir,
113113
"-results", resultsDir,
114-
confFile,
115-
)
114+
}
115+
if pgo {
116+
sweetRunArgs = append(sweetRunArgs, "-pgo")
117+
}
118+
sweetRunArgs = append(sweetRunArgs, confFile)
119+
cmd = exec.Command(sweetBin, sweetRunArgs...)
116120
cmd.Stdout = os.Stdout
117121
cmd.Stderr = os.Stderr
118122

@@ -129,29 +133,53 @@ func sweet(tcs []*toolchain) (err error) {
129133
}
130134
}()
131135

132-
// Dump results to stdout.
136+
dumpResults := func(filename string) error {
137+
// Print pkg and shortname tags because Sweet won't do it.
138+
benchName := filepath.Base(filepath.Dir(filename))
139+
fmt.Printf("pkg: golang.org/x/benchmarks/sweet/benchmarks/%s\n", benchName)
140+
fmt.Printf("shortname: sweet_%s\n", strings.ReplaceAll(benchName, "-", "_"))
141+
142+
// Dump results file.
143+
f, err := os.Open(filename)
144+
if err != nil {
145+
return fmt.Errorf("opening result %s: %v", filename, err)
146+
}
147+
defer f.Close()
148+
if _, err := io.Copy(os.Stdout, f); err != nil {
149+
return fmt.Errorf("reading result %s: %v", filename, err)
150+
}
151+
return nil
152+
}
153+
154+
// Dump non-PGO results to stdout.
155+
fmt.Printf("pgo: off\n")
133156
for _, tc := range tcs {
134157
matches, err := filepath.Glob(filepath.Join(resultsDir, "*", fmt.Sprintf("%s.results", tc.Name)))
135158
if err != nil {
136159
return fmt.Errorf("searching for results for %s in %s: %v", tc.Name, resultsDir, err)
137160
}
138161
fmt.Printf("toolchain: %s\n", tc.Name)
139162
for _, match := range matches {
140-
// Print pkg and shortname tags because Sweet won't do it.
141-
benchName := filepath.Base(filepath.Dir(match))
142-
fmt.Printf("pkg: golang.org/x/benchmarks/sweet/benchmarks/%s\n", benchName)
143-
fmt.Printf("shortname: sweet_%s\n", strings.ReplaceAll(benchName, "-", "_"))
163+
if err := dumpResults(match); err != nil {
164+
return err
165+
}
166+
}
167+
}
144168

145-
// Dump results file.
146-
f, err := os.Open(match)
169+
// Dump PGO results to stdout, if we expect them to exist.
170+
if pgo {
171+
fmt.Printf("pgo: on\n")
172+
for _, tc := range tcs {
173+
matches, err := filepath.Glob(filepath.Join(resultsDir, "*", fmt.Sprintf("%s.pgo.results", tc.Name)))
147174
if err != nil {
148-
return fmt.Errorf("opening result %s: %v", match, err)
175+
return fmt.Errorf("searching for PGO results for %s in %s: %v", tc.Name, resultsDir, err)
149176
}
150-
if _, err := io.Copy(os.Stdout, f); err != nil {
151-
f.Close()
152-
return fmt.Errorf("reading result %s: %v", match, err)
177+
fmt.Printf("toolchain: %s\n", tc.Name)
178+
for _, match := range matches {
179+
if err := dumpResults(match); err != nil {
180+
return err
181+
}
153182
}
154-
f.Close()
155183
}
156184
}
157185
return nil

0 commit comments

Comments
 (0)