aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2018-04-03 08:08:18 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-03 08:10:04 -0700
commita8023b796db7d05e329d0eb9a51cb4ce8222e4a0 (patch)
tree4c11435914e52a5f8b36c9796d169c41482b340c /src/main/java
parent81dbe79d09b4fa98d7803018b5d6d026e2e52a2e (diff)
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
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BuildSummaryStatsModule.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/SpawnStats.java106
2 files changed, 121 insertions, 0 deletions
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
@@ -81,6 +86,11 @@ public class BuildSummaryStatsModule extends BlazeModule {
}
@Subscribe
+ public void actionResultReceived(ActionResultReceivedEvent event) {
+ spawnStats.countActionResult(event.getActionResult());
+ }
+
+ @Subscribe
public void buildComplete(BuildCompleteEvent event) {
try {
// We might want to make this conditional on a flag; it can sometimes be a bit of a nuisance.
@@ -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<String> runners = ConcurrentHashMultiset.create();
+ private static final ImmutableList<String> 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<Multiset.Entry<String>> list = new ArrayList<>(runners.entrySet());
+ Collections.sort(list, Comparator.comparing(e -> e.getElement()));
+
+ for (Multiset.Entry<String> e : list) {
+ result.add(e.getElement(), e.getCount());
+ }
+
+ int total = result.spawnsCount();
+ return total + " process" + (total == 1 ? "" : "es") + result + ".";
+ }
+}