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