1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ 6 #define BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ 7 8 #include <stddef.h> 9 10 #include <map> 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "base/base_export.h" 16 #include "base/files/file_path.h" 17 #include "base/macros.h" 18 #include "base/strings/string16.h" 19 #include "base/synchronization/waitable_event.h" 20 #include "base/threading/platform_thread.h" 21 #include "base/time/time.h" 22 23 namespace base { 24 25 // Identifies an unknown module. 26 BASE_EXPORT extern const size_t kUnknownModuleIndex; 27 28 class NativeStackSamplerTestDelegate; 29 30 // StackSamplingProfiler periodically stops a thread to sample its stack, for 31 // the purpose of collecting information about which code paths are 32 // executing. This information is used in aggregate by UMA to identify hot 33 // and/or janky code paths. 34 // 35 // Sample StackSamplingProfiler usage: 36 // 37 // // Create and customize params as desired. 38 // base::StackStackSamplingProfiler::SamplingParams params; 39 // 40 // // To process the profiles, use a custom ProfileBuilder subclass: 41 // class SubProfileBuilder : 42 // public base::StackSamplingProfiler::ProfileBuilder{...} 43 // base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()), 44 // params, std::make_unique<SubProfileBuilder>(...)); 45 // 46 // profiler.Start(); 47 // // ... work being done on the target thread here ... 48 // profiler.Stop(); // optional, stops collection before complete per params 49 // 50 // The default SamplingParams causes stacks to be recorded in a single profile 51 // at a 10Hz interval for a total of 30 seconds. All of these parameters may be 52 // altered as desired. 53 // 54 // When a call stack profile is complete, or the profiler is stopped, 55 // ProfileBuilder's OnProfileCompleted function is called from a thread created 56 // by the profiler. 57 class BASE_EXPORT StackSamplingProfiler { 58 public: 59 // Module represents the module (DLL or exe) corresponding to a stack frame. 60 struct BASE_EXPORT Module { 61 Module(); 62 Module(uintptr_t base_address, 63 const std::string& id, 64 const FilePath& filename); 65 ~Module(); 66 67 // Points to the base address of the module. 68 uintptr_t base_address; 69 70 // An opaque binary string that uniquely identifies a particular program 71 // version with high probability. This is parsed from headers of the loaded 72 // module. 73 // For binaries generated by GNU tools: 74 // Contents of the .note.gnu.build-id field. 75 // On Windows: 76 // GUID + AGE in the debug image headers of a module. 77 std::string id; 78 79 // The filename of the module. 80 FilePath filename; 81 }; 82 83 // InternalModule represents the module (DLL or exe) and its validness state. 84 // Different from Module, it has an additional field "is_valid". 85 // 86 // This struct is only used for sampling data transfer from NativeStackSampler 87 // to ProfileBuilder. 88 struct BASE_EXPORT InternalModule { 89 InternalModule(); 90 InternalModule(uintptr_t base_address, 91 const std::string& id, 92 const FilePath& filename); 93 ~InternalModule(); 94 95 // Points to the base address of the module. 96 uintptr_t base_address; 97 98 // An opaque binary string that uniquely identifies a particular program 99 // version with high probability. This is parsed from headers of the loaded 100 // module. 101 // For binaries generated by GNU tools: 102 // Contents of the .note.gnu.build-id field. 103 // On Windows: 104 // GUID + AGE in the debug image headers of a module. 105 std::string id; 106 107 // The filename of the module. 108 FilePath filename; 109 110 // The validness of the module. 111 bool is_valid; 112 }; 113 114 // Frame represents an individual sampled stack frame with module information. 115 struct BASE_EXPORT Frame { 116 Frame(uintptr_t instruction_pointer, size_t module_index); 117 ~Frame(); 118 119 // Default constructor to satisfy IPC macros. Do not use explicitly. 120 Frame(); 121 122 // The sampled instruction pointer within the function. 123 uintptr_t instruction_pointer; 124 125 // Index of the module in CallStackProfile::modules. We don't represent 126 // module state directly here to save space. 127 size_t module_index; 128 }; 129 130 // InternalFrame represents an individual sampled stack frame with full module 131 // information. This is different from Frame which only contains module index. 132 // 133 // This struct is only used for sampling data transfer from NativeStackSampler 134 // to ProfileBuilder. 135 struct BASE_EXPORT InternalFrame { 136 InternalFrame(uintptr_t instruction_pointer, 137 InternalModule internal_module); 138 ~InternalFrame(); 139 140 // The sampled instruction pointer within the function. 141 uintptr_t instruction_pointer; 142 143 // The module information. 144 InternalModule internal_module; 145 }; 146 147 // Sample represents a set of stack frames with some extra information. 148 struct BASE_EXPORT Sample { 149 Sample(); 150 Sample(const Sample& sample); 151 ~Sample(); 152 153 // These constructors are used only during testing. 154 Sample(const Frame& frame); 155 Sample(const std::vector<Frame>& frames); 156 157 // The entire stack frame when the sample is taken. 158 std::vector<Frame> frames; 159 160 // A bit-field indicating which process milestones have passed. This can be 161 // used to tell where in the process lifetime the samples are taken. Just 162 // as a "lifetime" can only move forward, these bits mark the milestones of 163 // the processes life as they occur. Bits can be set but never reset. The 164 // actual definition of the individual bits is left to the user of this 165 // module. 166 uint32_t process_milestones = 0; 167 }; 168 169 // CallStackProfile represents a set of samples. 170 struct BASE_EXPORT CallStackProfile { 171 CallStackProfile(); 172 CallStackProfile(CallStackProfile&& other); 173 ~CallStackProfile(); 174 175 CallStackProfile& operator=(CallStackProfile&& other); 176 177 CallStackProfile CopyForTesting() const; 178 179 std::vector<Module> modules; 180 std::vector<Sample> samples; 181 182 // Duration of this profile. 183 TimeDelta profile_duration; 184 185 // Time between samples. 186 TimeDelta sampling_period; 187 188 private: 189 // Copying is possible but expensive so disallow it except for internal use 190 // (i.e. CopyForTesting); use std::move instead. 191 CallStackProfile(const CallStackProfile& other); 192 193 DISALLOW_ASSIGN(CallStackProfile); 194 }; 195 196 // Represents parameters that configure the sampling. 197 struct BASE_EXPORT SamplingParams { 198 // Time to delay before first samples are taken. 199 TimeDelta initial_delay = TimeDelta::FromMilliseconds(0); 200 201 // Number of samples to record per profile. 202 int samples_per_profile = 300; 203 204 // Interval between samples during a sampling profile. This is the desired 205 // duration from the start of one sample to the start of the next sample. 206 TimeDelta sampling_interval = TimeDelta::FromMilliseconds(100); 207 }; 208 209 // Testing support. These methods are static beause they interact with the 210 // sampling thread, a singleton used by all StackSamplingProfiler objects. 211 // These methods can only be called by the same thread that started the 212 // sampling. 213 class BASE_EXPORT TestAPI { 214 public: 215 // Resets the internal state to that of a fresh start. This is necessary 216 // so that tests don't inherit state from previous tests. 217 static void Reset(); 218 219 // Returns whether the sampling thread is currently running or not. 220 static bool IsSamplingThreadRunning(); 221 222 // Disables inherent idle-shutdown behavior. 223 static void DisableIdleShutdown(); 224 225 // Initiates an idle shutdown task, as though the idle timer had expired, 226 // causing the thread to exit. There is no "idle" check so this must be 227 // called only when all sampling tasks have completed. This blocks until 228 // the task has been executed, though the actual stopping of the thread 229 // still happens asynchronously. Watch IsSamplingThreadRunning() to know 230 // when the thread has exited. If |simulate_intervening_start| is true then 231 // this method will make it appear to the shutdown task that a new profiler 232 // was started between when the idle-shutdown was initiated and when it 233 // runs. 234 static void PerformSamplingThreadIdleShutdown( 235 bool simulate_intervening_start); 236 }; 237 238 // The ProfileBuilder interface allows the user to record profile information 239 // on the fly in whatever format is desired. Functions are invoked by the 240 // profiler on its own thread so must not block or perform expensive 241 // operations. 242 class BASE_EXPORT ProfileBuilder { 243 public: 244 ProfileBuilder() = default; 245 virtual ~ProfileBuilder() = default; 246 247 // Metadata associated with the sample to be saved off. 248 // The code implementing this method must not do anything that could acquire 249 // a mutex, including allocating memory (which includes LOG messages) 250 // because that mutex could be held by a stopped thread, thus resulting in 251 // deadlock. 252 virtual void RecordAnnotations() = 0; 253 254 // Records a new set of internal frames. Invoked when sampling a sample 255 // completes. 256 virtual void OnSampleCompleted( 257 std::vector<InternalFrame> internal_frames) = 0; 258 259 // Finishes the profile construction with |profile_duration| and 260 // |sampling_period|. Invoked when sampling a profile completes. 261 virtual void OnProfileCompleted(TimeDelta profile_duration, 262 TimeDelta sampling_period) = 0; 263 264 private: 265 DISALLOW_COPY_AND_ASSIGN(ProfileBuilder); 266 }; 267 268 // Creates a profiler for the CURRENT thread. An optional |test_delegate| can 269 // be supplied by tests. The caller must ensure that this object gets 270 // destroyed before the current thread exits. 271 StackSamplingProfiler( 272 const SamplingParams& params, 273 std::unique_ptr<ProfileBuilder> profile_builder, 274 NativeStackSamplerTestDelegate* test_delegate = nullptr); 275 276 // Creates a profiler for ANOTHER thread. An optional |test_delegate| can be 277 // supplied by tests. 278 // 279 // IMPORTANT: The caller must ensure that the thread being sampled does not 280 // exit before this object gets destructed or Bad Things(tm) may occur. 281 StackSamplingProfiler( 282 PlatformThreadId thread_id, 283 const SamplingParams& params, 284 std::unique_ptr<ProfileBuilder> profile_builder, 285 NativeStackSamplerTestDelegate* test_delegate = nullptr); 286 287 // Stops any profiling currently taking place before destroying the profiler. 288 // This will block until profile_builder_'s OnProfileCompleted function has 289 // executed if profiling has started but not already finished. 290 ~StackSamplingProfiler(); 291 292 // Initializes the profiler and starts sampling. Might block on a 293 // WaitableEvent if this StackSamplingProfiler was previously started and 294 // recently stopped, while the previous profiling phase winds down. 295 void Start(); 296 297 // Stops the profiler and any ongoing sampling. This method will return 298 // immediately with the profile_builder_'s OnProfileCompleted function being 299 // run asynchronously. At most one more stack sample will be taken after this 300 // method returns. Calling this function is optional; if not invoked profiling 301 // terminates when all the profiling samples specified in the SamplingParams 302 // are completed or the profiler object is destroyed, whichever occurs first. 303 void Stop(); 304 305 private: 306 friend class TestAPI; 307 308 // SamplingThread is a separate thread used to suspend and sample stacks from 309 // the target thread. 310 class SamplingThread; 311 312 // The thread whose stack will be sampled. 313 PlatformThreadId thread_id_; 314 315 const SamplingParams params_; 316 317 // Receives the sampling data and builds a CallStackProfile. The ownership of 318 // this object will be transferred to the sampling thread when thread sampling 319 // starts. 320 std::unique_ptr<ProfileBuilder> profile_builder_; 321 322 // This starts "signaled", is reset when sampling begins, and is signaled 323 // when that sampling is complete and the profile_builder_'s 324 // OnProfileCompleted function has executed. 325 WaitableEvent profiling_inactive_; 326 327 // An ID uniquely identifying this profiler to the sampling thread. This 328 // will be an internal "null" value when no collection has been started. 329 int profiler_id_; 330 331 // Stored until it can be passed to the NativeStackSampler created in Start(). 332 NativeStackSamplerTestDelegate* const test_delegate_; 333 334 DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler); 335 }; 336 337 // These operators permit types to be compared and used in a map of Samples, as 338 // done in tests and by the metrics provider code. 339 BASE_EXPORT bool operator==(const StackSamplingProfiler::Module& a, 340 const StackSamplingProfiler::Module& b); 341 BASE_EXPORT bool operator==(const StackSamplingProfiler::Sample& a, 342 const StackSamplingProfiler::Sample& b); 343 BASE_EXPORT bool operator!=(const StackSamplingProfiler::Sample& a, 344 const StackSamplingProfiler::Sample& b); 345 BASE_EXPORT bool operator<(const StackSamplingProfiler::Sample& a, 346 const StackSamplingProfiler::Sample& b); 347 BASE_EXPORT bool operator==(const StackSamplingProfiler::Frame& a, 348 const StackSamplingProfiler::Frame& b); 349 BASE_EXPORT bool operator<(const StackSamplingProfiler::Frame& a, 350 const StackSamplingProfiler::Frame& b); 351 352 } // namespace base 353 354 #endif // BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ 355