tools/perfmon: Don't stop on errors Don't terminate on first error. Sleep a bit and try again. Post a message to a gerrit change if it cannot be built. The fact the PS has a message from perfmon will prevent it from retrying the same change. Remove trailing newlines from log.Printf() messages, they're automatically added. Bug: tint:1383 Change-Id: I78a627c53c492e7da33a74470d5a064e90a7a753 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/78783 Auto-Submit: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ryan Harrison <rharrison@chromium.org> Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/tools/src/cmd/perfmon/main.go b/tools/src/cmd/perfmon/main.go index 21f1057..f01fcff 100644 --- a/tools/src/cmd/perfmon/main.go +++ b/tools/src/cmd/perfmon/main.go
@@ -112,50 +112,16 @@ } for true { - { - log.Println("scanning for review changes to benchmark...") - change, err := e.findGerritChangeToBenchmark() - if err != nil { - return err - } - if change != nil { - if err := e.benchmarkGerritChange(*change); err != nil { - return err - } - continue - } + didSomething, err := e.doSomeWork() + if err != nil { + log.Printf("ERROR: %v", err) + time.Sleep(time.Minute * 10) + continue } - - { - log.Println("scanning for submitted changes to benchmark...") - changesToBenchmark, err := e.changesToBenchmark() - if err != nil { - return err - } - - if len(changesToBenchmark) > 0 { - log.Printf("benchmarking %v changes...\n", len(changesToBenchmark)) - for i, c := range changesToBenchmark { - log.Printf("benchmarking %v/%v....\n", i+1, len(changesToBenchmark)) - benchRes, err := e.benchmarkTintChange(c) - if err != nil { - return err - } - commitRes, err := e.benchmarksToCommitResults(c, *benchRes) - if err != nil { - return err - } - log.Printf("pushing results...\n") - if err := e.pushUpdatedResults(*commitRes); err != nil { - return err - } - } - continue - } + if !didSomething { + log.Println("nothing to do. Sleeping...") + time.Sleep(time.Minute * 5) } - - log.Println("nothing to do. Sleeping...") - time.Sleep(time.Minute * 5) } return nil @@ -281,6 +247,53 @@ benchmarkCache map[git.Hash]*bench.Run } +// doSomeWork scans gerrit for changes up for review and submitted changes to +// benchmark. If something was found to do, then returns true. +func (e env) doSomeWork() (bool, error) { + { + log.Println("scanning for review changes to benchmark...") + change, err := e.findGerritChangeToBenchmark() + if err != nil { + return true, err + } + if change != nil { + if err := e.benchmarkGerritChange(*change); err != nil { + return true, err + } + return true, nil + } + } + + { + log.Println("scanning for submitted changes to benchmark...") + changesToBenchmark, err := e.changesToBenchmark() + if err != nil { + return true, err + } + + if len(changesToBenchmark) > 0 { + log.Printf("benchmarking %v changes...", len(changesToBenchmark)) + for i, c := range changesToBenchmark { + log.Printf("benchmarking %v/%v....", i+1, len(changesToBenchmark)) + benchRes, err := e.benchmarkTintChange(c) + if err != nil { + return true, err + } + commitRes, err := e.benchmarksToCommitResults(c, *benchRes) + if err != nil { + return true, err + } + log.Printf("pushing results...") + if err := e.pushUpdatedResults(*commitRes); err != nil { + return true, err + } + } + return true, nil + } + } + return false, nil +} + // changesToBenchmark fetches the list of changes that do not currently have // benchmark results, which should be benchmarked. func (e env) changesToBenchmark() ([]git.Hash, error) { @@ -319,11 +332,11 @@ // dependencies, builds tint, then runs the benchmarks, returning the results. func (e env) benchmarkTintChange(hash git.Hash) (*bench.Run, error) { if cached, ok := e.benchmarkCache[hash]; ok { - log.Printf("reusing cached benchmark results of '%v'...\n", hash) + log.Printf("reusing cached benchmark results of '%v'...", hash) return cached, nil } - log.Printf("checking out tint at '%v'...\n", hash) + log.Printf("checking out tint at '%v'...", hash) if err := checkout(hash, e.tintRepo); err != nil { return nil, err } @@ -345,6 +358,8 @@ return run, nil } +// benchmarksToCommitResults converts the benchmarks in the provided bench.Run +// to a CommitResults. func (e env) benchmarksToCommitResults(hash git.Hash, results bench.Run) (*CommitResults, error) { commits, err := e.tintRepo.Log(&git.LogOptions{ From: hash.String(), @@ -502,8 +517,7 @@ if !reflect.DeepEqual(res.System, e.system) { log.Printf(`WARNING: results file '%v' has different system information! File: %+v -System: %+v -`, path, res.System, e.system) +System: %+v`, path, res.System, e.system) } return res, nil @@ -546,14 +560,24 @@ "-DTINT_BUILD_WGSL_WRITER=1", "-DTINT_BUILD_BENCHMARKS=1", ); err != nil { - return fmt.Errorf("failed to generate tint build config:\n %w", err) + return errFailedToBuild{fmt.Errorf("failed to generate tint build config:\n %w", err)} } if _, err := call(tools.ninja, e.buildDir, e.cfg.Timeouts.Build); err != nil { - return fmt.Errorf("failed to build tint:\n %w", err) + return errFailedToBuild{err} } return nil } +// errFailedToBuild is the error returned by buildTint() if the build failed +type errFailedToBuild struct { + // The reason + reason error +} + +func (e errFailedToBuild) Error() string { + return fmt.Sprintf("failed to build: %v", e.reason) +} + // benchmarkTint runs the tint benchmarks, returning the results. func (e env) benchmarkTint() (*bench.Run, error) { exe := filepath.Join(e.buildDir, "tint-benchmark") @@ -666,7 +690,7 @@ }) if len(candidates) > 0 { - log.Printf("%d gerrit changes to benchmark\n", len(candidates)) + log.Printf("%d gerrit changes to benchmark", len(candidates)) return &candidates[0].change, nil } return nil, nil @@ -675,7 +699,7 @@ // benchmarks the gerrit change, posting the findings to the change func (e env) benchmarkGerritChange(change gerrit.ChangeInfo) error { current := change.Revisions[change.CurrentRevision] - log.Printf("fetching '%v'...\n", current.Ref) + log.Printf("fetching '%v'...", current.Ref) currentHash, err := e.tintRepo.Fetch(current.Ref, &git.FetchOptions{Auth: e.cfg.Tint.Auth}) if err != nil { return err @@ -685,8 +709,25 @@ if err != nil { return fmt.Errorf("failed to parse parent hash '%v':\n %v", parent, err) } + + postMsg := func(notify, msg string) error { + _, _, err = e.gerrit.Changes.SetReview(change.ChangeID, currentHash.String(), &gerrit.ReviewInput{ + Message: msg, + Tag: "autogenerated:perfmon", + Notify: notify, + }) + if err != nil { + return fmt.Errorf("failed to post message to gerrit change:\n %v", err) + } + return nil + } + newRun, err := e.benchmarkTintChange(currentHash) if err != nil { + var ftb errFailedToBuild + if errors.As(err, &ftb) { + return postMsg("OWNER", fmt.Sprintf("patchset %v failed to build", current.Number)) + } return err } if _, err := e.tintRepo.Fetch(parent, &git.FetchOptions{Auth: e.cfg.Tint.Auth}); err != nil { @@ -735,15 +776,7 @@ if len(diff) > 0 { notify = "OWNER_REVIEWERS" } - _, _, err = e.gerrit.Changes.SetReview(change.ChangeID, currentHash.String(), &gerrit.ReviewInput{ - Message: msg.String(), - Tag: "autogenerated:perfmon", - Notify: notify, - }) - if err != nil { - return fmt.Errorf("failed to post benchmark results to gerrit change:\n %v", err) - } - return nil + return postMsg(notify, msg.String()) } // createOrOpenGitRepo creates a new local repo by cloning cfg.URL into