Improve output of the `dump` command with `--skyframe=detailed`.
* Output deps in groups. This helps to better visualize how the skyframe requests are made.
* Add a flag `--skyfunction_filter` to filter output to certain functions.
PiperOrigin-RevId: 419829752
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
index b7a5b72..dc0e08b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
@@ -36,6 +36,9 @@
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor.RuleStat;
+import com.google.devtools.build.lib.util.RegexFilter;
+import com.google.devtools.build.lib.util.RegexFilter.RegexFilterConverter;
+import com.google.devtools.build.skyframe.MemoizingEvaluator;
import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
@@ -56,7 +59,6 @@
/** Implementation of the dump command. */
@Command(
- allowResidue = false,
mustRunInWorkspace = false,
options = {DumpCommand.DumpOptions.class},
help =
@@ -70,8 +72,8 @@
public class DumpCommand implements BlazeCommand {
/**
- * NB! Any changes to this class must be kept in sync with anyOutput variable
- * value in the {@link DumpCommand#exec(CommandEnvironment,OptionsProvider)} method below.
+ * NB! Any changes to this class must be kept in sync with anyOutput variable value in the {@link
+ * DumpCommand#exec} method below.
*/
public static class DumpOptions extends OptionsBase {
@@ -130,6 +132,15 @@
help = "Dump Skyframe graph: 'off', 'summary', or 'detailed'."
)
public SkyframeDumpOption dumpSkyframe;
+
+ @Option(
+ name = "skyfunction_filter",
+ defaultValue = ".*",
+ converter = RegexFilterConverter.class,
+ documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
+ effectTags = {OptionEffectTag.BAZEL_MONITORING},
+ help = "Regex filter of SkyFunction names to output. Only used with --skyframe=detailed.")
+ public RegexFilter skyFunctionFilter;
}
/**
@@ -161,7 +172,7 @@
|| dumpOptions.dumpRuleClasses
|| dumpOptions.dumpRules
|| dumpOptions.starlarkMemory != null
- || (dumpOptions.dumpSkyframe != SkyframeDumpOption.OFF);
+ || dumpOptions.dumpSkyframe != SkyframeDumpOption.OFF;
if (!anyOutput) {
Collection<Class<? extends OptionsBase>> optionList = new ArrayList<>();
optionList.add(DumpOptions.class);
@@ -219,10 +230,17 @@
}
}
- if (dumpOptions.dumpSkyframe != SkyframeDumpOption.OFF) {
- dumpSkyframe(
- env.getSkyframeExecutor(), dumpOptions.dumpSkyframe == SkyframeDumpOption.SUMMARY, out);
- out.println();
+ MemoizingEvaluator evaluator = env.getSkyframeExecutor().getEvaluator();
+ switch (dumpOptions.dumpSkyframe) {
+ case OFF:
+ break;
+ case SUMMARY:
+ evaluator.dumpSummary(out);
+ break;
+ case DETAILED:
+ evaluator.dumpDetailed(
+ out, k -> dumpOptions.skyFunctionFilter.test(k.functionName().getName()));
+ break;
}
return failure.orElse(BlazeCommandResult.success());
@@ -242,10 +260,6 @@
return true;
}
- private static void dumpSkyframe(SkyframeExecutor executor, boolean summarize, PrintStream out) {
- executor.dump(summarize, out);
- }
-
private static void dumpRuleClasses(BlazeRuntime runtime, PrintStream out) {
PackageFactory factory = runtime.getPackageFactory();
List<String> ruleClassNames = new ArrayList<>(factory.getRuleClassNames());
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index e3ebb9b..8ddec32 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -722,10 +722,6 @@
fileCache, actionInputPrefetcher, DiscoveredModulesPruner.DEFAULT);
}
- public void dump(boolean summarize, PrintStream out) {
- memoizingEvaluator.dump(summarize, out);
- }
-
@ForOverride
protected abstract void dumpPackages(PrintStream out);
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
index 374ccbc..5b385b6 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -13,8 +13,6 @@
// limitations under the License.
package com.google.devtools.build.skyframe;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@@ -26,6 +24,7 @@
import com.google.devtools.build.lib.profiler.GoogleAutoProfilerUtils;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
+import com.google.devtools.build.lib.util.GroupedList;
import com.google.devtools.build.skyframe.Differencer.Diff;
import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DeletingInvalidationState;
import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingInvalidationState;
@@ -366,39 +365,48 @@
}
@Override
- public void dump(boolean summarize, PrintStream out) {
- if (summarize) {
- long nodes = 0;
- long edges = 0;
- for (InMemoryNodeEntry entry : graph.getAllValues().values()) {
- nodes++;
- if (entry.isDone()) {
- edges += Iterables.size(entry.getDirectDeps());
- }
- }
- out.println("Node count: " + nodes);
- out.println("Edge count: " + edges);
- } else {
- Function<SkyKey, String> keyFormatter =
- key ->
- String.format(
- "%s:%s", key.functionName(), key.argument().toString().replace('\n', '_'));
-
- for (Map.Entry<SkyKey, InMemoryNodeEntry> mapPair : graph.getAllValues().entrySet()) {
- SkyKey key = mapPair.getKey();
- InMemoryNodeEntry entry = mapPair.getValue();
- if (entry.isDone()) {
- out.print(keyFormatter.apply(key));
- out.print("|");
- if (entry.keepEdges() == NodeEntry.KeepEdgesPolicy.NONE) {
- out.println(" (direct deps not stored)");
- } else {
- out.println(
- Joiner.on('|').join(Iterables.transform(entry.getDirectDeps(), keyFormatter)));
- }
- }
+ public void dumpSummary(PrintStream out) {
+ long nodes = 0;
+ long edges = 0;
+ for (InMemoryNodeEntry entry : graph.getAllValues().values()) {
+ nodes++;
+ if (entry.isDone()) {
+ edges += Iterables.size(entry.getDirectDeps());
}
}
+ out.println("Node count: " + nodes);
+ out.println("Edge count: " + edges);
+ }
+
+ @Override
+ public void dumpDetailed(PrintStream out, Predicate<SkyKey> filter) {
+ graph
+ .getAllValues()
+ .forEach(
+ (key, entry) -> {
+ if (!filter.test(key) || !entry.isDone()) {
+ return;
+ }
+ printKey(key, out);
+ if (entry.keepEdges() == NodeEntry.KeepEdgesPolicy.NONE) {
+ out.println(" (direct deps not stored)");
+ } else {
+ GroupedList<SkyKey> deps =
+ GroupedList.create(entry.getCompressedDirectDepsForDoneEntry());
+ for (int i = 0; i < deps.listSize(); i++) {
+ out.format(" Group %d:\n", i + 1);
+ for (SkyKey dep : deps.get(i)) {
+ out.print(" ");
+ printKey(dep, out);
+ }
+ }
+ }
+ out.println();
+ });
+ }
+
+ private static void printKey(SkyKey key, PrintStream out) {
+ out.format("%s:%s\n", key.functionName(), key.argument().toString().replace('\n', '_'));
}
public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctionsForTesting() {
diff --git a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
index 89fa0e3..808df9c 100644
--- a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java
@@ -177,11 +177,21 @@
}
/**
- * Write the graph to the output stream. Not necessarily thread-safe. Use only for debugging
- * purposes.
+ * Writes a brief summary about the graph to the given output stream.
+ *
+ * <p>Not necessarily thread-safe. Use only for debugging purposes.
*/
@ThreadHostile
- void dump(boolean summarize, PrintStream out);
+ void dumpSummary(PrintStream out);
+
+ /**
+ * Writes a detailed summary of the graph to the given output stream, omitting keys that do not
+ * match the given filter.
+ *
+ * <p>Not necessarily thread-safe. Use only for debugging purposes.
+ */
+ @ThreadHostile
+ void dumpDetailed(PrintStream out, Predicate<SkyKey> filter);
/** A supplier for creating instances of a particular evaluator implementation. */
interface EvaluatorSupplier {