1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_PROFILER_SAMPLE_METADATA_H_
6 #define BASE_PROFILER_SAMPLE_METADATA_H_
8 #include "base/base_export.h"
9 #include "base/profiler/metadata_recorder.h"
10 #include "base/strings/string_piece.h"
11 #include "base/threading/platform_thread.h"
12 #include "third_party/abseil-cpp/absl/types/optional.h"
14 // -----------------------------------------------------------------------------
15 // Usage documentation
16 // -----------------------------------------------------------------------------
19 // These functions provide a means to control the metadata attached to samples
20 // collected by the stack sampling profiler. SampleMetadataScope controls the
21 // scope covered by the metadata (thread, process).
23 // Any samples collected by the sampling profiler will include the active
24 // metadata. This enables us to later analyze targeted subsets of samples
25 // (e.g. those collected during paint or layout).
29 // void DidStartLoad() {
30 // is_loading_metadata_.Set(1);
33 // void DidFinishLoad() {
34 // is_loading_metadata_.Remove();
37 // base::SampleMetadata is_loading_metadata_;
39 // Alternatively, ScopedSampleMetadata can be used to ensure that the metadata
40 // is removed correctly.
44 // void DoExpensiveWork() {
45 // base::ScopedSampleMetadata metadata("xyz", 1);
60 enum class SampleMetadataScope {
61 // All threads in the current process will have the associated metadata
62 // attached to their samples.
64 // The metadata will only be attached to samples for the current thread.
68 class BASE_EXPORT SampleMetadata {
70 // Set the metadata value associated with |name| to be recorded for |scope|.
71 explicit SampleMetadata(StringPiece name, SampleMetadataScope scope);
73 SampleMetadata(const SampleMetadata&) = default;
74 ~SampleMetadata() = default;
76 SampleMetadata& operator=(const SampleMetadata&) = delete;
78 // Set the metadata value associated with |name| in the process-global stack
79 // sampling profiler metadata, overwriting any previous value set for that
81 void Set(int64_t value);
83 // Set the metadata value associated with the pair (|name|, |key|) in the
84 // process-global stack sampling profiler metadata, overwriting any previous
85 // value set for that (|name|, |key|) pair. This constructor allows the
86 // metadata to be associated with an additional user-defined key. One might
87 // supply a key based on the frame id, for example, to distinguish execution
88 // in service of scrolling between different frames. Prefer the previous
89 // function if no user-defined metadata is required. Note: values specified
90 // for a name and key are stored separately from values specified with only a
92 void Set(int64_t key, int64_t value);
94 // Removes the metadata item with the specified name from the process-global
95 // stack sampling profiler metadata.
97 // If such an item doesn't exist, this has no effect.
100 // Removes the metadata item with the specified (|name|, |key|) pair from the
101 // process-global stack sampling profiler metadata. This function does not
102 // alter values set with the name |name| but no key.
104 // If such an item doesn't exist, this has no effect.
105 void Remove(int64_t key);
108 const uint64_t name_hash_;
109 // Scope is kept as-is instead of retrieving a PlatformThreadId in case
110 // Set()/Remove() is called on a thread different from where the object was
112 const SampleMetadataScope scope_;
115 class BASE_EXPORT ScopedSampleMetadata {
117 // Set the metadata value associated with |name| for |scope|.
118 ScopedSampleMetadata(StringPiece name,
120 SampleMetadataScope scope);
122 // Set the metadata value associated with the pair (|name|, |key|) for
123 // |scope|. This constructor allows the metadata to be associated with an
124 // additional user-defined key. One might supply a key based on the frame id,
125 // for example, to distinguish execution in service of scrolling between
126 // different frames. Prefer the previous constructor if no user-defined
127 // metadata is required. Note: values specified for a name and key are stored
128 // separately from values specified with only a name.
129 ScopedSampleMetadata(StringPiece name,
132 SampleMetadataScope scope);
134 ScopedSampleMetadata(const ScopedSampleMetadata&) = delete;
135 ~ScopedSampleMetadata();
137 ScopedSampleMetadata& operator=(const ScopedSampleMetadata&) = delete;
140 const uint64_t name_hash_;
141 absl::optional<int64_t> key_;
142 absl::optional<PlatformThreadId> thread_id_;
145 // Applies the specified metadata to samples already recorded between
146 // |period_start| and |period_end| in all thread's active profiles, subject to
147 // the condition that the profile fully encompasses the period and the profile
148 // has not already completed. The condition ensures that the metadata is applied
149 // only if all execution during its scope was seen in the profile. This avoids
150 // biasng the samples towards the 'middle' of the execution seen during the
151 // metadata scope (i.e. because the start or end of execution was missed), at
152 // the cost of missing execution that are longer than the profiling period, or
153 // extend before or after it. |period_end| must be <= TimeTicks::Now().
154 BASE_EXPORT void ApplyMetadataToPastSamples(TimeTicks period_start,
155 TimeTicks period_end,
158 SampleMetadataScope scope);
159 BASE_EXPORT void ApplyMetadataToPastSamples(TimeTicks period_start,
160 TimeTicks period_end,
164 SampleMetadataScope scope);
166 // Adds metadata as metadata global to the sampling profile. Has the effect of
167 // applying the metadata to all samples in the profile, even ones collected
168 // earlier in time. This is probably not what you want for most use cases;
169 // prefer using SampleMetadata / ScopedSampleMetadata /
170 // ApplyMetadataToPastSamples instead.
171 BASE_EXPORT void AddProfileMetadata(StringPiece name,
174 SampleMetadataScope scope);
176 // Returns the process-global metadata recorder instance used for tracking
177 // sampling profiler metadata.
179 // This function should not be called by non-profiler related code.
180 BASE_EXPORT MetadataRecorder* GetSampleMetadataRecorder();
184 #endif // BASE_PROFILER_SAMPLE_METADATA_H_