1 // Copyright 2015 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_STACK_SAMPLING_PROFILER_H_
6 #define BASE_PROFILER_STACK_SAMPLING_PROFILER_H_
11 #include "base/base_export.h"
12 #include "base/functional/callback.h"
13 #include "base/profiler/profile_builder.h"
14 #include "base/profiler/sampling_profiler_thread_token.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/threading/platform_thread.h"
17 #include "base/time/time.h"
18 #include "third_party/abseil-cpp/absl/types/optional.h"
24 class StackSamplerTestDelegate;
26 // StackSamplingProfiler periodically stops a thread to sample its stack, for
27 // the purpose of collecting information about which code paths are
28 // executing. This information is used in aggregate by UMA to identify hot
29 // and/or janky code paths.
31 // Sample StackSamplingProfiler usage:
33 // // Create and customize params as desired.
34 // base::StackStackSamplingProfiler::SamplingParams params;
36 // // Create a ProfileBuilder subclass to process the profiles.
37 // class ProfileBuilder : public base::ProfileBuilder {...}
39 // // Then create the profiler:
40 // base::StackSamplingProfiler profiler(
41 // GetSamplingProfilerCurrentThreadToken(),
43 // std::make_unique<ProfileBuilder>(...));
45 // // On Android the caller also must provide a factory function for creating
46 // // its core stack unwinders. See the ThreadProfiler implementation for an
47 // // example of how to do this.
48 // base::StackSamplingProfiler profiler(
49 // GetSamplingProfilerCurrentThreadToken(),
51 // std::make_unique<ProfileBuilder>(...),
52 // core_unwinders_factory);
54 // // Then start the profiling.
57 // // ... work being done on the target thread here ...
59 // // Optionally stop collection before complete per params.
62 // The default SamplingParams causes stacks to be recorded in a single profile
63 // at a 10Hz interval for a total of 30 seconds. All of these parameters may be
64 // altered as desired.
66 // When a call stack profile is complete, or the profiler is stopped,
67 // ProfileBuilder's OnProfileCompleted function is called from a thread created
69 class BASE_EXPORT StackSamplingProfiler {
71 // Factory for generating a set of Unwinders for use by the profiler. More
72 // general unwinders should appear before more specific unwinders in the
73 // generated vector, e.g. a system unwinder should appear before a Chrome
74 // unwinder. The callback will be invoked on the profiler thread.
75 using UnwindersFactory =
76 OnceCallback<std::vector<std::unique_ptr<Unwinder>>()>;
78 // Represents parameters that configure the sampling.
79 struct BASE_EXPORT SamplingParams {
80 // Time to delay before first samples are taken.
81 TimeDelta initial_delay = Milliseconds(0);
83 // Number of samples to record per profile.
84 int samples_per_profile = 300;
86 // Interval between samples during a sampling profile. This is the desired
87 // duration from the start of one sample to the start of the next sample.
88 TimeDelta sampling_interval = Milliseconds(100);
91 // Returns true if the profiler is supported on the current platform
93 static bool IsSupportedForCurrentPlatform();
95 // Creates a profiler for the the thread associated with |thread_token|,
96 // generated by GetSamplingProfilerCurrentThreadToken().
97 // |core_unwinders_factory| is required on Android since the unwinders are
98 // provided outside StackSamplingProfiler, but must be null other platforms.
99 // |record_sample_callback| is called for each sample right before recording
100 // the stack sample. An optional |test_delegate| can be supplied by tests.
102 // The caller must ensure that this object gets destroyed before the thread
104 StackSamplingProfiler(
105 SamplingProfilerThreadToken thread_token,
106 const SamplingParams& params,
107 std::unique_ptr<ProfileBuilder> profile_builder,
108 UnwindersFactory core_unwinders_factory = UnwindersFactory(),
109 RepeatingClosure record_sample_callback = RepeatingClosure(),
110 StackSamplerTestDelegate* test_delegate = nullptr);
112 StackSamplingProfiler(const StackSamplingProfiler&) = delete;
113 StackSamplingProfiler& operator=(const StackSamplingProfiler&) = delete;
115 // Stops any profiling currently taking place before destroying the profiler.
116 // This will block until profile_builder_'s OnProfileCompleted function has
117 // executed if profiling has started but not already finished.
118 ~StackSamplingProfiler();
120 // Initializes the profiler and starts sampling. Might block on a
121 // WaitableEvent if this StackSamplingProfiler was previously started and
122 // recently stopped, while the previous profiling phase winds down.
125 // Stops the profiler and any ongoing sampling. This method will return
126 // immediately with the profile_builder_'s OnProfileCompleted function being
127 // run asynchronously. At most one more stack sample will be taken after this
128 // method returns. Calling this function is optional; if not invoked profiling
129 // terminates when all the profiling samples specified in the SamplingParams
130 // are completed or the profiler object is destroyed, whichever occurs first.
133 // Adds an auxiliary unwinder to handle additional, non-native-code unwind
135 void AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder);
137 // Test peer class. These functions are purely for internal testing of
138 // StackSamplingProfiler; DO NOT USE within tests outside of this directory.
139 // The functions are static because they interact with the sampling thread, a
140 // singleton used by all StackSamplingProfiler objects. The functions can
141 // only be called by the same thread that started the sampling.
142 class BASE_EXPORT TestPeer {
144 // Resets the internal state to that of a fresh start. This is necessary
145 // so that tests don't inherit state from previous tests.
148 // Returns whether the sampling thread is currently running or not.
149 static bool IsSamplingThreadRunning();
151 // Disables inherent idle-shutdown behavior.
152 static void DisableIdleShutdown();
154 // Initiates an idle shutdown task, as though the idle timer had expired,
155 // causing the thread to exit. There is no "idle" check so this must be
156 // called only when all sampling tasks have completed. This blocks until
157 // the task has been executed, though the actual stopping of the thread
158 // still happens asynchronously. Watch IsSamplingThreadRunning() to know
159 // when the thread has exited. If |simulate_intervening_start| is true then
160 // this method will make it appear to the shutdown task that a new profiler
161 // was started between when the idle-shutdown was initiated and when it
163 static void PerformSamplingThreadIdleShutdown(
164 bool simulate_intervening_start);
166 // Provides access to the method computing the next sample time.
167 static TimeTicks GetNextSampleTime(TimeTicks scheduled_current_sample_time,
168 TimeDelta sampling_interval,
173 // SamplingThread is a separate thread used to suspend and sample stacks from
174 // the target thread.
175 class SamplingThread;
177 // Friend the global functions from sample_metadata.cc so that it can call
178 // into the function below.
179 friend void ApplyMetadataToPastSamplesImpl(
180 TimeTicks period_start,
181 TimeTicks period_end,
183 absl::optional<int64_t> key,
185 absl::optional<PlatformThreadId> thread_id);
186 friend void AddProfileMetadataImpl(
190 absl::optional<PlatformThreadId> thread_id);
192 // Apply metadata to already recorded samples. See the
193 // ApplyMetadataToPastSamples() docs in sample_metadata.h.
194 static void ApplyMetadataToPastSamples(
195 TimeTicks period_start,
196 TimeTicks period_end,
198 absl::optional<int64_t> key,
200 absl::optional<PlatformThreadId> thread_id);
202 // Adds metadata as metadata global to the sampling profile.
203 static void AddProfileMetadata(uint64_t name_hash,
206 absl::optional<PlatformThreadId> thread_id);
208 // The thread whose stack will be sampled.
209 SamplingProfilerThreadToken thread_token_;
211 const SamplingParams params_;
213 // Receives the sampling data and builds a profile. The ownership of this
214 // object will be transferred to the sampling thread when thread sampling
216 std::unique_ptr<ProfileBuilder> profile_builder_;
218 // Stack sampler which stops the thread and collects stack frames. The
219 // ownership of this object will be transferred to the sampling thread when
220 // thread sampling starts.
221 std::unique_ptr<StackSampler> sampler_;
223 // This starts "signaled", is reset when sampling begins, and is signaled
224 // when that sampling is complete and the profile_builder_'s
225 // OnProfileCompleted function has executed.
226 WaitableEvent profiling_inactive_;
228 // An ID uniquely identifying this profiler to the sampling thread. This
229 // will be an internal "null" value when no collection has been started.
235 #endif // BASE_PROFILER_STACK_SAMPLING_PROFILER_H_