From a8023b796db7d05e329d0eb9a51cb4ce8222e4a0 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 3 Apr 2018 08:08:18 -0700 Subject: Add stats about cache hits and execution strategies to Bazel's UI. Fixes: 2846 RELNOTES: Bazel now displays information about remote cache hits and execution strategies used in its UI after every build and test, and adds a corresponding line "process stats" to BuildToolLogs in BEP. PiperOrigin-RevId: 191441770 --- .../build/lib/runtime/BuildSummaryStatsModule.java | 15 +++ .../devtools/build/lib/runtime/SpawnStats.java | 106 +++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 src/main/java/com/google/devtools/build/lib/runtime/SpawnStats.java (limited to 'src/main/java') diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BuildSummaryStatsModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BuildSummaryStatsModule.java index 927355d9a9..4d2cdcef78 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/BuildSummaryStatsModule.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/BuildSummaryStatsModule.java @@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import com.google.devtools.build.lib.actions.ActionKeyContext; +import com.google.devtools.build.lib.actions.ActionResultReceivedEvent; import com.google.devtools.build.lib.buildeventstream.BuildToolLogs; import com.google.devtools.build.lib.buildtool.BuildRequest; import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent; @@ -50,11 +51,14 @@ public class BuildSummaryStatsModule extends BlazeModule { private boolean enabled; private boolean discardActions; + private SpawnStats spawnStats; + @Override public void beforeCommand(CommandEnvironment env) { this.reporter = env.getReporter(); this.eventBus = env.getEventBus(); this.actionKeyContext = env.getSkyframeExecutor().getActionKeyContext(); + this.spawnStats = new SpawnStats(); eventBus.register(this); } @@ -63,6 +67,7 @@ public class BuildSummaryStatsModule extends BlazeModule { this.criticalPathComputer = null; this.eventBus = null; this.reporter = null; + this.spawnStats = null; } @Override @@ -80,6 +85,11 @@ public class BuildSummaryStatsModule extends BlazeModule { } } + @Subscribe + public void actionResultReceived(ActionResultReceivedEvent event) { + spawnStats.countActionResult(event.getActionResult()); + } + @Subscribe public void buildComplete(BuildCompleteEvent event) { try { @@ -115,6 +125,11 @@ public class BuildSummaryStatsModule extends BlazeModule { } reporter.handle(Event.info(Joiner.on(", ").join(items))); + + String spawnSummary = spawnStats.getSummary(); + reporter.handle(Event.info(spawnSummary)); + statistics.add(Pair.of("process stats", ByteString.copyFromUtf8(spawnSummary))); + reporter.post(new BuildToolLogs(statistics, ImmutableList.of())); } finally { criticalPathComputer = null; diff --git a/src/main/java/com/google/devtools/build/lib/runtime/SpawnStats.java b/src/main/java/com/google/devtools/build/lib/runtime/SpawnStats.java new file mode 100644 index 0000000000..dcb68ca8a9 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/runtime/SpawnStats.java @@ -0,0 +1,106 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.runtime; + +import com.google.common.collect.ConcurrentHashMultiset; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multiset; +import com.google.devtools.build.lib.actions.ActionResult; +import com.google.devtools.build.lib.actions.SpawnResult; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import javax.annotation.concurrent.ThreadSafe; + +/** Collects results from SpawnResult. */ +@ThreadSafe +class SpawnStats { + private final ConcurrentHashMultiset runners = ConcurrentHashMultiset.create(); + private static final ImmutableList REPORT_FIRST = ImmutableList.of("remote cache hit"); + + public void countActionResult(ActionResult actionResult) { + for (SpawnResult r : actionResult.spawnResults()) { + countRunnerName(r.getRunnerName()); + } + } + + public void countRunnerName(String runner) { + runners.add(runner); + } + + private static class ResultString { + StringBuilder result = new StringBuilder(); + String firstRunner; + int spawnsCount = 0; + int runnersNum = 0; + + public int spawnsCount() { + return spawnsCount; + } + + public void add(String name, int count) { + spawnsCount += count; + runnersNum += 1; + + if (runnersNum == 1) { + firstRunner = name; + } + + if (result.length() > 0) { + result.append(", "); + } + result.append(count); + result.append(" "); + result.append(name); + } + + @Override + public String toString() { + if (runnersNum == 0) { + return ""; + } + if (runnersNum == 1) { + return ", " + firstRunner; + } + return ": " + result; + } + } + + /* + * Returns a human-readable summary of spawns counted. + */ + public String getSummary() { + ResultString result = new ResultString(); + + // First report cache results. + for (String s : REPORT_FIRST) { + int count = runners.setCount(s, 0); + if (count > 0) { + result.add(s, count); + } + } + + // Sort the rest alphabetically + ArrayList> list = new ArrayList<>(runners.entrySet()); + Collections.sort(list, Comparator.comparing(e -> e.getElement())); + + for (Multiset.Entry e : list) { + result.add(e.getElement(), e.getCount()); + } + + int total = result.spawnsCount(); + return total + " process" + (total == 1 ? "" : "es") + result + "."; + } +} -- cgit v1.2.3