[pinpoint] Add bot Id to dimensions for pairwise execution
Mentioning botId in the dimensions is required to make sure that
the benchmark is run on a specific device
Bug: b/321304277
Change-Id: I4eec79dbf62a9e8e1f9f97e0c8bd0e4153c58522
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/834716
Reviewed-by: Leina Sun <sunxiaodi@google.com>
Commit-Queue: Vidit Chitkara <viditchitkara@google.com>
diff --git a/pinpoint/go/run_benchmark/run_benchmark.go b/pinpoint/go/run_benchmark/run_benchmark.go
index 0dbd30b..4a40caf 100644
--- a/pinpoint/go/run_benchmark/run_benchmark.go
+++ b/pinpoint/go/run_benchmark/run_benchmark.go
@@ -75,7 +75,7 @@
}
// Run schedules a swarming task to run the RunBenchmarkRequest.
-func Run(ctx context.Context, sc backends.SwarmingClient, commit, bot, benchmark, story, storyTag string, jobID string, buildArtifact *spb.SwarmingRpcsCASReference, iter int) ([]*spb.SwarmingRpcsTaskRequestMetadata, error) {
+func Run(ctx context.Context, sc backends.SwarmingClient, commit, bot, benchmark, story, storyTag string, jobID string, buildArtifact *spb.SwarmingRpcsCASReference, iter int, dimensions []map[string]string) ([]*spb.SwarmingRpcsTaskRequestMetadata, error) {
botConfig, err := bot_configs.GetBotConfig(bot, false)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to create benchmark test object")
@@ -86,7 +86,11 @@
return nil, skerr.Wrapf(err, "Failed to prepare benchmark test for execution")
}
- swarmingRequest := createSwarmingRequest(jobID, bt.GetCommand(), buildArtifact, botConfig.Dimensions)
+ dims := botConfig.Dimensions
+ if dimensions != nil {
+ dims = append(dims, dimensions...)
+ }
+ swarmingRequest := createSwarmingRequest(jobID, bt.GetCommand(), buildArtifact, dims)
resp := make([]*spb.SwarmingRpcsTaskRequestMetadata, 0)
for i := 0; i < iter; i++ {
diff --git a/pinpoint/go/run_benchmark/run_benchmark_test.go b/pinpoint/go/run_benchmark/run_benchmark_test.go
index 0beb76a..0aa6d1a 100644
--- a/pinpoint/go/run_benchmark/run_benchmark_test.go
+++ b/pinpoint/go/run_benchmark/run_benchmark_test.go
@@ -51,7 +51,7 @@
Return(&swarmingV1.SwarmingRpcsTaskRequestMetadata{
TaskId: "123",
}, nil).Once()
- taskIds, err := Run(ctx, sc, c, "android-pixel2_webview-perf", "performance_browser_tests", "story", "all", fakeID, buildArtifact, 1)
+ taskIds, err := Run(ctx, sc, c, "android-pixel2_webview-perf", "performance_browser_tests", "story", "all", fakeID, buildArtifact, 1, nil)
assert.NoError(t, err)
assert.Equal(t, 1, len(taskIds))
assert.Equal(t, "123", taskIds[0].TaskId)
diff --git a/pinpoint/go/workflows/internal/commits_runner.go b/pinpoint/go/workflows/internal/commits_runner.go
index 35befe7..632b692 100644
--- a/pinpoint/go/workflows/internal/commits_runner.go
+++ b/pinpoint/go/workflows/internal/commits_runner.go
@@ -121,17 +121,21 @@
return runs
}
-func runBenchmark(ctx workflow.Context, cc *midpoint.CombinedCommit, cas *swarmingV1.SwarmingRpcsCASReference, scrp *SingleCommitRunnerParams) (*workflows.TestRun, error) {
+func runBenchmark(ctx workflow.Context, cc *midpoint.CombinedCommit, cas *swarmingV1.SwarmingRpcsCASReference, scrp *SingleCommitRunnerParams, dimensions []map[string]string, iteration int64) (*workflows.TestRun, error) {
var tr *workflows.TestRun
- if err := workflow.ExecuteChildWorkflow(ctx, workflows.RunBenchmark, &RunBenchmarkParams{
- JobID: scrp.PinpointJobID,
- Commit: cc,
- BotConfig: scrp.BotConfig,
- BuildCAS: cas,
- Benchmark: scrp.Benchmark,
- Story: scrp.Story,
- StoryTags: scrp.StoryTags,
- }).Get(ctx, &tr); err != nil {
+ rbp := &RunBenchmarkParams{
+ JobID: scrp.PinpointJobID,
+ Commit: cc,
+ BotConfig: scrp.BotConfig,
+ BuildCAS: cas,
+ Benchmark: scrp.Benchmark,
+ Story: scrp.Story,
+ StoryTags: scrp.StoryTags,
+ Dimensions: dimensions,
+ IterationIdx: iteration,
+ }
+
+ if err := workflow.ExecuteChildWorkflow(ctx, workflows.RunBenchmark, rbp).Get(ctx, &tr); err != nil {
return nil, err
}
@@ -175,10 +179,14 @@
ctx = workflow.WithChildOptions(ctx, runBenchmarkWorkflowOptions)
ctx = workflow.WithActivityOptions(ctx, regularActivityOptions)
for i := 0; i < int(sc.Iterations); i++ {
+ // We need to make a copy of i since the following is a closure. By making a
+ // copy every closure will point to it's own copy of i rather than pointing to
+ // the same variable.
+ iteration := int64(i)
workflow.Go(ctx, func(gCtx workflow.Context) {
defer wg.Done()
- tr, err := runBenchmark(gCtx, sc.CombinedCommit, b.CAS, sc)
+ tr, err := runBenchmark(gCtx, sc.CombinedCommit, b.CAS, sc, nil, iteration)
if err != nil {
ec.Send(gCtx, err)
diff --git a/pinpoint/go/workflows/internal/pairwise_runner.go b/pinpoint/go/workflows/internal/pairwise_runner.go
index 645dfaa..8c600d4 100644
--- a/pinpoint/go/workflows/internal/pairwise_runner.go
+++ b/pinpoint/go/workflows/internal/pairwise_runner.go
@@ -35,7 +35,7 @@
//
// The function makes a swarming API call internally to fetch the desired bots. If successful, a slice
// of bot ids is returned
-func FindAvailableBotsActivity(ctx context.Context, botConfig string) ([]string, error) {
+func FindAvailableBotsActivity(ctx context.Context, botConfig string, seed int64) ([]string, error) {
sc, err := backends.NewSwarmingClient(ctx, backends.DefaultSwarmingServiceAddress)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to initialize swarming client")
@@ -51,6 +51,13 @@
botIds[i] = b.BotId
}
+ // The list of bot ids is randomized to make sure that the tasks
+ // do not everytime pick the same set of bots and leave the remaining
+ // unused almost the entire time.
+ rand.New(rand.NewSource(seed)).Shuffle(len(botIds), func(i, j int) {
+ botIds[i], botIds[j] = botIds[j], botIds[i]
+ })
+
return botIds, nil
}
@@ -83,7 +90,7 @@
ctx = workflow.WithChildOptions(ctx, runBenchmarkWorkflowOptions)
var botIds []string
- if err := workflow.ExecuteActivity(ctx, FindAvailableBotsActivity, pc.BotConfig).Get(ctx, &botIds); err != nil {
+ if err := workflow.ExecuteActivity(ctx, FindAvailableBotsActivity, pc.BotConfig, pc.Seed).Get(ctx, &botIds); err != nil {
return nil, err
}
@@ -95,17 +102,22 @@
// TODO(b/332391612): viditchitkara@ Build chrome for leftBuild and rightBuild in parallel
// to save time.
- leftBuild, err := buildChrome(ctx, pc.PinpointJobID, pc.BotConfig, pc.Benchmark, pc.LeftBuild.Commit)
- if err != nil {
- return nil, skerr.Wrapf(err, "unable to build chrome for commit %s", pc.LeftBuild.Commit.Main.GitHash)
- }
- pc.LeftBuild = *leftBuild
- rightBuild, err := buildChrome(ctx, pc.PinpointJobID, pc.BotConfig, pc.Benchmark, pc.RightBuild.Commit)
- if err != nil {
- return nil, skerr.Wrapf(err, "unable to build chrome for commit %s", pc.RightBuild.Commit.Main.GitHash)
+ if pc.LeftBuild.CAS == nil {
+ leftBuild, err := buildChrome(ctx, pc.PinpointJobID, pc.BotConfig, pc.Benchmark, pc.LeftBuild.Commit)
+ if err != nil {
+ return nil, skerr.Wrapf(err, "unable to build chrome for commit %s", pc.LeftBuild.Commit.Main.GitHash)
+ }
+ pc.LeftBuild = *leftBuild
}
- pc.RightBuild = *rightBuild
+
+ if pc.RightBuild.CAS == nil {
+ rightBuild, err := buildChrome(ctx, pc.PinpointJobID, pc.BotConfig, pc.Benchmark, pc.RightBuild.Commit)
+ if err != nil {
+ return nil, skerr.Wrapf(err, "unable to build chrome for commit %s", pc.RightBuild.Commit.Main.GitHash)
+ }
+ pc.RightBuild = *rightBuild
+ }
pairs := generatePairIndices(pc.Seed, int(pc.Iterations))
runs := []struct {
@@ -130,12 +142,22 @@
orders := [][2]int{{0, 1}, {1, 0}}
for i := 0; i < int(pc.Iterations); i++ {
pairIdx := pairs[i]
+ botDimension := []map[string]string{
+ {
+ "key": "id",
+ "value": botIds[i%len(botIds)],
+ },
+ }
+
+ // We need to make a copy of i since the following is a closure. By making a
+ // copy every closure will point to it's own copy of i rather than pointing to
+ // the same variable.
+ iteration := int64(i)
workflow.Go(ctx, func(gCtx workflow.Context) {
defer wg.Done()
for _, idx := range orders[pairIdx] {
- // TODO(viditchitkara@): append bot id to the dimension so they only run on the given bot.
- tr, err := runBenchmark(gCtx, runs[idx].cc, runs[idx].cas, &pc.SingleCommitRunnerParams)
+ tr, err := runBenchmark(gCtx, runs[idx].cc, runs[idx].cas, &pc.SingleCommitRunnerParams, botDimension, iteration)
if err != nil {
ec.Send(gCtx, err)
continue
diff --git a/pinpoint/go/workflows/internal/run_benchmark.go b/pinpoint/go/workflows/internal/run_benchmark.go
index 61ef1ae..e5b8e92 100644
--- a/pinpoint/go/workflows/internal/run_benchmark.go
+++ b/pinpoint/go/workflows/internal/run_benchmark.go
@@ -32,6 +32,12 @@
Story string
// story tags for the test
StoryTags string
+ // additional dimensions for bot selection
+ Dimensions []map[string]string
+ // iteration for the benchmark run. A few workflows have multiple iterations of
+ // benchmark runs and this param comes in handy to get additional info of a specific run.
+ // This is for debugging/informational purposes only.
+ IterationIdx int64
}
// RunBenchmarkActivity wraps RunBenchmarkWorkflow in Activities
@@ -97,7 +103,7 @@
return "", skerr.Wrap(err)
}
- taskIds, err := run_benchmark.Run(ctx, sc, rbp.Commit.GetMainGitHash(), rbp.BotConfig, rbp.Benchmark, rbp.Story, rbp.StoryTags, rbp.JobID, rbp.BuildCAS, 1)
+ taskIds, err := run_benchmark.Run(ctx, sc, rbp.Commit.GetMainGitHash(), rbp.BotConfig, rbp.Benchmark, rbp.Story, rbp.StoryTags, rbp.JobID, rbp.BuildCAS, 1, rbp.Dimensions)
if err != nil {
return "", err
}
diff --git a/pinpoint/go/workflows/sample/main.go b/pinpoint/go/workflows/sample/main.go
index dafcdb8..7a74947 100644
--- a/pinpoint/go/workflows/sample/main.go
+++ b/pinpoint/go/workflows/sample/main.go
@@ -29,6 +29,7 @@
commit = flag.String("commit", "611b5a084486cd6d99a0dad63f34e320a2ebc2b3", "Git commit hash to build Chrome.")
triggerBisectFlag = flag.Bool("bisect", false, "toggle true to trigger bisect workflow")
triggerSingleCommitFlag = flag.Bool("single-commit", false, "toggle true to trigger single commit runner workflow")
+ triggerPairwiseFlag = flag.Bool("pairwise", false, "toggle true to trigger pairwise commit runner workflow")
)
func defaultWorkflowOptions() client.StartWorkflowOptions {
@@ -77,6 +78,62 @@
return be
}
+func triggerPairwiseRunner(c client.Client) *internal.PairwiseRun {
+ ctx := context.Background()
+ // based off of https://pinpoint-dot-chromeperf.appspot.com/job/179a34b2be0000
+ p := &internal.PairwiseCommitsRunnerParams{
+ SingleCommitRunnerParams: internal.SingleCommitRunnerParams{
+ PinpointJobID: "179a34b2be0000",
+ BotConfig: "android-pixel4-perf",
+ Benchmark: "blink_perf.bindings",
+ Story: "gc-mini-tree.html",
+ Chart: "gc-mini-tree",
+ AggregationMethod: "mean",
+ CombinedCommit: midpoint.NewCombinedCommit(&pb.Commit{GitHash: *commit}),
+ Iterations: 6,
+ },
+ Seed: 54321,
+ LeftBuild: workflows.Build{
+ BuildChromeParams: workflows.BuildChromeParams{
+ Commit: midpoint.NewCombinedCommit(&pb.Commit{GitHash: "573a50658f4301465569c3faf00a145093a1fe9b"}), // 1284448
+ },
+ CAS: &swarmingV1.SwarmingRpcsCASReference{
+ CasInstance: "projects/chrome-swarming/instances/default_instance",
+ Digest: &swarmingV1.SwarmingRpcsDigest{
+ Hash: "062ccf0a30a362d8e4df3c9b82172a78e3d62c2990eb30927f5863a6b08e80bb",
+ SizeBytes: 810,
+ },
+ },
+ },
+ RightBuild: workflows.Build{
+ BuildChromeParams: workflows.BuildChromeParams{
+ Commit: midpoint.NewCombinedCommit(&pb.Commit{GitHash: "a633e198b79b2e0c83c72a3006cdffe642871e22"}), // 1284449
+ },
+ CAS: &swarmingV1.SwarmingRpcsCASReference{
+ CasInstance: "projects/chrome-swarming/instances/default_instance",
+ Digest: &swarmingV1.SwarmingRpcsDigest{
+ Hash: "51845150f953c33ee4c0900589ba916ca28b7896806460aa8935c0de2b209db6",
+ SizeBytes: 810,
+ },
+ },
+ },
+ }
+
+ var pr *internal.PairwiseRun
+ we, err := c.ExecuteWorkflow(ctx, defaultWorkflowOptions(), workflows.PairwiseCommitsRunner, p)
+ if err != nil {
+ sklog.Fatalf("Unable to execute workflow: %v", err)
+ return nil
+ }
+ sklog.Infof("Started workflow.. WorkflowID: %v RunID: %v", we.GetID(), we.GetRunID())
+
+ if err := we.Get(ctx, &pr); err != nil {
+ sklog.Fatalf("Unable to get result: %v", err)
+ return nil
+ }
+ return pr
+}
+
func triggerSingleCommitRunner(c client.Client) *internal.CommitRun {
ctx := context.Background()
p := &internal.SingleCommitRunnerParams{
@@ -159,4 +216,8 @@
result := triggerSingleCommitRunner(c)
sklog.Infof("Workflow result: %v", spew.Sdump(result))
}
+ if *triggerPairwiseFlag {
+ result := triggerPairwiseRunner(c)
+ sklog.Infof("Workflow result: %v", spew.Sdump(result))
+ }
}