When tracking the critical path, if not keeping incremental state, don't keep references to actions indefinitely. Instead, once an action is finished executing, keep just some metadata about it. This allows actions to be unconditionally dropped when running with --batch, --discard_analysis_cache, and --keep_going, even if profiling is enabled.

The additional fields here add between 8 and 12 bytes per component, and we have one component per action. This additional penalty is only incurred when we are already saving memory, so I think it's ok. The full penalty will be realized only towards the end of the build, when every action has started executing at least once. Users can still specify --noexperimental_enable_critical_path_profiling if they want to squeeze even more memory out.

PiperOrigin-RevId: 152328870
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 705a00a..0061e3f 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
@@ -41,6 +41,7 @@
   private EventBus eventBus;
   private Reporter reporter;
   private boolean enabled;
+  private boolean discardActions;
 
   @Override
   public void beforeCommand(Command command, CommandEnvironment env) {
@@ -59,12 +60,13 @@
   @Override
   public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorBuilder builder) {
     enabled = env.getOptions().getOptions(ExecutionOptions.class).enableCriticalPathProfiling;
+    discardActions = !env.getSkyframeExecutor().hasIncrementalState();
   }
 
   @Subscribe
   public void executionPhaseStarting(ExecutionStartingEvent event) {
     if (enabled) {
-      criticalPathComputer = new SimpleCriticalPathComputer(BlazeClock.instance());
+      criticalPathComputer = new SimpleCriticalPathComputer(BlazeClock.instance(), discardActions);
       eventBus.register(criticalPathComputer);
     }
   }
@@ -88,10 +90,12 @@
         // when the actions were executed while critical path computation is stored in the reverse
         // way.
         for (SimpleCriticalPathComponent stat : criticalPath.components().reverse()) {
-          Profiler.instance().logSimpleTaskDuration(
-              stat.getStartNanos(),
-              stat.getElapsedTimeNanos(),
-              ProfilerTask.CRITICAL_PATH_COMPONENT, stat.getAction());
+          Profiler.instance()
+              .logSimpleTaskDuration(
+                  stat.getStartNanos(),
+                  stat.getElapsedTimeNanos(),
+                  ProfilerTask.CRITICAL_PATH_COMPONENT,
+                  stat.prettyPrintAction());
         }
         Profiler.instance().completeTask(ProfilerTask.CRITICAL_PATH);
       }