diff options
author | philwo <philwo@google.com> | 2017-08-31 13:28:41 +0200 |
---|---|---|
committer | Vladimir Moskva <vladmos@google.com> | 2017-08-31 18:25:28 +0200 |
commit | e9e35aa49ad41974430d46e52836e255e77d6a50 (patch) | |
tree | dc24a8b388b3cc4a54042c58ec6d4535d6247f83 /src/main/java/com/google/devtools/build/lib/profiler/Profiler.java | |
parent | 930f7036a71d5d66cc643cdcffc7d92da664cf42 (diff) |
Split the cycle between vfs and profiler.
- Move ProfilerInfo into a subpackage (it's not necessary for profiling, just for analyzing a profile).
- Make some fields in Profiler public for ProfileInfo.
- Mark Profiler as ThreadSafe; there's no cyclic dependency here.
This is based on ulfjack's microbazel patch series: https://github.com/ulfjack/bazel/commit/44553fcac0fc876784d8f48c2e577d8c999712de
PiperOrigin-RevId: 167121952
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/profiler/Profiler.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/profiler/Profiler.java | 72 |
1 files changed, 35 insertions, 37 deletions
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 d4a7ca14b6..2ad353f6da 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 @@ -18,6 +18,8 @@ import static com.google.devtools.build.lib.profiler.ProfilerTask.TASK_COUNT; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; +import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.profiler.PredicateBasedStatRecorder.RecorderAndPredicate; import com.google.devtools.build.lib.profiler.StatRecorder.VfsHeuristics; import com.google.devtools.build.lib.util.Clock; @@ -45,28 +47,27 @@ import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; /** - * Blaze internal profiler. Provides facility to report various Blaze tasks and - * store them (asynchronously) in the file for future analysis. - * <p> - * Implemented as singleton so any caller should use Profiler.instance() to - * obtain reference. - * <p> - * Internally, profiler uses two data structures - ThreadLocal task stack to track - * nested tasks and single ConcurrentLinkedQueue to gather all completed tasks. - * <p> - * Also, due to the nature of the provided functionality (instrumentation of all - * Blaze components), build.lib.profiler package will be used by almost every - * other Blaze package, so special attention should be paid to avoid any - * dependencies on the rest of the Blaze code, including build.lib.util and - * build.lib.vfs. This is important because build.lib.util and build.lib.vfs - * contain Profiler invocations and any dependency on those two packages would - * create circular relationship. - * <p> - * All gathered instrumentation data will be stored in the file. Please, note, - * that while file format is described here it is considered internal and can - * change at any time. For scripting, using blaze analyze-profile --dump=raw - * would be more robust and stable solution. + * Blaze internal profiler. Provides facility to report various Blaze tasks and store them + * (asynchronously) in the file for future analysis. + * + * <p>Implemented as singleton so any caller should use Profiler.instance() to obtain reference. + * + * <p>Internally, profiler uses two data structures - ThreadLocal task stack to track nested tasks + * and single ConcurrentLinkedQueue to gather all completed tasks. + * + * <p>Also, due to the nature of the provided functionality (instrumentation of all Blaze + * components), build.lib.profiler package will be used by almost every other Blaze package, so + * special attention should be paid to avoid any dependencies on the rest of the Blaze code, + * including build.lib.util and build.lib.vfs. This is important because build.lib.util and + * build.lib.vfs contain Profiler invocations and any dependency on those two packages would create + * circular relationship. + * + * <p>All gathered instrumentation data will be stored in the file. Please, note, that while file + * format is described here it is considered internal and can change at any time. For scripting, + * using blaze analyze-profile --dump=raw would be more robust and stable solution. + * * <p> + * * <pre> * Profiler file consists of the deflated stream with following overall structure: * HEADER @@ -115,19 +116,19 @@ import java.util.zip.DeflaterOutputStream; * * @see ProfilerTask enum for recognized task types. */ -//@ThreadSafe - commented out to avoid cyclic dependency with lib.util package +@ThreadSafe public final class Profiler { private static final Logger LOG = Logger.getLogger(Profiler.class.getName()); - static final int MAGIC = 0x11223344; + public static final int MAGIC = 0x11223344; // File version number. Note that merely adding new record types in // the ProfilerTask does not require bumping version number as long as original // enum values are not renamed or deleted. - static final int VERSION = 0x03; + public static final int VERSION = 0x03; // EOF marker. Must be < 0. - static final int EOF_MARKER = -1; + public static final int EOF_MARKER = -1; // Profiler will check for gathered data and persist all of it in the // separate thread every SAVE_DELAY ms. @@ -140,11 +141,8 @@ public final class Profiler { private static final int HISTOGRAM_BUCKETS = 20; - /** - * - * A task that was very slow. - */ - public final class SlowTask implements Comparable<SlowTask> { + /** A task that was very slow. */ + public static final class SlowTask implements Comparable<SlowTask> { final long durationNanos; final Object object; ProfilerTask type; @@ -187,7 +185,7 @@ public final class Profiler { * Class itself is not thread safe, but all access to it from Profiler * methods is. */ - //@ThreadCompatible - commented out to avoid cyclic dependency with lib.util. + @ThreadCompatible private final class TaskData { final long threadId; final long startTime; @@ -240,7 +238,7 @@ public final class Profiler { * However, ArrayDeque is 1.6 only. For 1.5 best approach would be to utilize * ArrayList and emulate stack using it. */ - //@ThreadSafe - commented out to avoid cyclic dependency with lib.util. + @ThreadSafe private final class TaskStack extends ThreadLocal<List<TaskData>> { @Override @@ -293,11 +291,11 @@ public final class Profiler { } /** - * Implements datastore for object description indices. Intended to be used - * only by the Profiler.save() method. + * Implements datastore for object description indices. Intended to be used only by the + * Profiler.save() method. */ - //@ThreadCompatible - commented out to avoid cyclic dependency with lib.util. - private final class ObjectDescriber { + @ThreadCompatible + private static final class ObjectDescriber { private Map<Object, Integer> descMap = new IdentityHashMap<>(2000); private int indexCounter = 0; @@ -337,7 +335,7 @@ public final class Profiler { * lock if they do the same operation at the same time. Access to the individual queues is * synchronized on the queue objects themselves. */ - private final class SlowestTaskAggregator { + private static final class SlowestTaskAggregator { private static final int SHARDS = 16; private final int size; |