Allow to configure the additional profile tasks to be included in the JSON profile
Closes #7217.
PiperOrigin-RevId: 238656293
diff --git a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
index f740286..a7b9cb0 100644
--- a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
+++ b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
@@ -19,6 +19,7 @@
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.collect.Extrema;
@@ -386,67 +387,8 @@
}
}
- /**
- * Which {@link ProfilerTask}s are profiled.
- */
- public enum ProfiledTaskKinds {
- /**
- * Do not profile anything.
- *
- * <p>Performance is best with this case, but we lose critical path analysis and slowest
- * operation tracking.
- */
- NONE {
- @Override
- boolean isProfiling(ProfilerTask type) {
- return false;
- }
- },
-
- /**
- * Profile on a few, known-to-be-slow tasks.
- *
- * <p>Performance is somewhat decreased in comparison to {@link #NONE}, but we still track the
- * slowest operations (VFS).
- */
- SLOWEST {
- @Override
- boolean isProfiling(ProfilerTask type) {
- return type.collectsSlowestInstances();
- }
- },
-
- /** A set of tasks that's useful for the Json trace output. */
- ALL_FOR_TRACE {
- @Override
- boolean isProfiling(ProfilerTask type) {
- return !type.isVfs()
- // CRITICAL_PATH corresponds to writing the file.
- && type != ProfilerTask.CRITICAL_PATH
- && type != ProfilerTask.SKYFUNCTION
- && type != ProfilerTask.ACTION_COMPLETE
- && !type.isStarlark();
- }
- },
-
- /**
- * Profile all tasks.
- *
- * <p>This is in use when {@code --profile} is specified.
- */
- ALL {
- @Override
- boolean isProfiling(ProfilerTask type) {
- return true;
- }
- };
-
- /** Whether the Profiler collects data for the given task type. */
- abstract boolean isProfiling(ProfilerTask type);
- }
-
private Clock clock;
- private ProfiledTaskKinds profiledTaskKinds;
+ private ImmutableSet<ProfilerTask> profiledTasks;
private volatile long profileStartTime;
private volatile boolean recordAllDurations = false;
@@ -537,7 +479,7 @@
* <p>Subsequent calls to beginTask/endTask will be recorded in the provided output stream. Please
* note that stream performance is extremely important and buffered streams should be utilized.
*
- * @param profiledTaskKinds which kinds of {@link ProfilerTask}s to track
+ * @param profiledTasks which of {@link ProfilerTask}s to track
* @param stream output stream to store profile data. Note: passing unbuffered stream object
* reference may result in significant performance penalties
* @param comment a comment to insert in the profile data
@@ -547,7 +489,7 @@
* @param execStartTimeNanos execution start time in nanos obtained from {@code clock.nanoTime()}
*/
public synchronized void start(
- ProfiledTaskKinds profiledTaskKinds,
+ ImmutableSet<ProfilerTask> profiledTasks,
OutputStream stream,
Format format,
String comment,
@@ -559,7 +501,7 @@
Preconditions.checkState(!isActive(), "Profiler already active");
initHistograms();
- this.profiledTaskKinds = profiledTaskKinds;
+ this.profiledTasks = profiledTasks;
this.clock = clock;
// sanity check for current limitation on the number of supported types due
@@ -661,7 +603,7 @@
}
public boolean isProfiling(ProfilerTask type) {
- return profiledTaskKinds.isProfiling(type);
+ return profiledTasks.contains(type);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index fbef84c..9e9d1ae 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -18,6 +18,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
@@ -46,7 +47,6 @@
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.Profiler.Format;
-import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.query2.AbstractBlazeQueryEnvironment;
@@ -279,7 +279,7 @@
long waitTimeInMs) {
OutputStream out = null;
boolean recordFullProfilerData = false;
- ProfiledTaskKinds profiledTasks = ProfiledTaskKinds.NONE;
+ ImmutableSet.Builder<ProfilerTask> profiledTasksBuilder = ImmutableSet.builder();
Profiler.Format format = Profiler.Format.BINARY_BAZEL_FORMAT;
Path profilePath = null;
try {
@@ -300,20 +300,37 @@
recordFullProfilerData = false;
out = profilePath.getOutputStream();
eventHandler.handle(Event.info("Writing tracer profile to '" + profilePath + "'"));
- profiledTasks = ProfiledTaskKinds.ALL_FOR_TRACE;
+ for (ProfilerTask profilerTask : ProfilerTask.values()) {
+ if (!profilerTask.isVfs()
+ // CRITICAL_PATH corresponds to writing the file.
+ && profilerTask != ProfilerTask.CRITICAL_PATH
+ && profilerTask != ProfilerTask.SKYFUNCTION
+ && profilerTask != ProfilerTask.ACTION_COMPLETE
+ && !profilerTask.isStarlark()) {
+ profiledTasksBuilder.add(profilerTask);
+ }
+ }
+ profiledTasksBuilder.addAll(options.additionalProfileTasks);
} else if (options.profilePath != null) {
profilePath = workspace.getWorkspace().getRelative(options.profilePath);
recordFullProfilerData = options.recordFullProfilerData;
out = profilePath.getOutputStream();
eventHandler.handle(Event.info("Writing profile data to '" + profilePath + "'"));
- profiledTasks = ProfiledTaskKinds.ALL;
+ for (ProfilerTask profilerTask : ProfilerTask.values()) {
+ profiledTasksBuilder.add(profilerTask);
+ }
} else if (options.alwaysProfileSlowOperations) {
recordFullProfilerData = false;
out = null;
- profiledTasks = ProfiledTaskKinds.SLOWEST;
+ for (ProfilerTask profilerTask : ProfilerTask.values()) {
+ if (profilerTask.collectsSlowestInstances()) {
+ profiledTasksBuilder.add(profilerTask);
+ }
+ }
}
- if (profiledTasks != ProfiledTaskKinds.NONE) {
+ ImmutableSet<ProfilerTask> profiledTasks = profiledTasksBuilder.build();
+ if (!profiledTasks.isEmpty()) {
Profiler profiler = Profiler.instance();
profiler.start(
profiledTasks,
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
index 0a8fac9..9452400 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommonCommandOptions.java
@@ -16,11 +16,13 @@
import static com.google.common.base.Strings.isNullOrEmpty;
import com.google.devtools.build.lib.profiler.MemoryProfiler.MemoryProfileStableHeapParameters;
+import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.runtime.CommandLineEvent.ToolCommandLineEvent;
import com.google.devtools.build.lib.util.OptionsUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters;
+import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
@@ -221,6 +223,16 @@
public boolean enableCpuUsageProfiling;
@Option(
+ name = "experimental_profile_additional_tasks",
+ converter = ProfilerTaskConverter.class,
+ defaultValue = "none",
+ allowMultiple = true,
+ documentationCategory = OptionDocumentationCategory.LOGGING,
+ effectTags = {OptionEffectTag.AFFECTS_OUTPUTS, OptionEffectTag.BAZEL_MONITORING},
+ help = "Specifies additional profile tasks to be included in the profile.")
+ public List<ProfilerTask> additionalProfileTasks;
+
+ @Option(
name = "profile",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.LOGGING,
@@ -416,4 +428,11 @@
+ "one."
)
public boolean keepStateAfterBuild;
+
+ /** The option converter to check that the user can only specify legal profiler tasks. */
+ public static class ProfilerTaskConverter extends EnumConverter<ProfilerTask> {
+ public ProfilerTaskConverter() {
+ super(ProfilerTask.class, "profiler task");
+ }
+ }
}