| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/profiler/stack_sampling_profiler.h" | 5 #include "base/profiler/stack_sampling_profiler.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/memory/singleton.h" | 11 #include "base/memory/singleton.h" |
| 12 #include "base/profiler/native_stack_sampler.h" | 12 #include "base/profiler/native_stack_sampler.h" |
| 13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
| 14 #include "base/timer/elapsed_timer.h" | 14 #include "base/timer/elapsed_timer.h" |
| 15 | 15 |
| 16 namespace base { | 16 namespace base { |
| 17 | 17 |
| 18 // PendingProfiles ------------------------------------------------------------ | 18 // DefaultProfileProcessor ---------------------------------------------------- |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // Thread-safe singleton class that stores collected call stack profiles waiting | 22 // Singleton class responsible for providing the default processing for profiles |
| 23 // to be processed. | 23 // (i.e. for profiles generated by profilers without their own completed |
| 24 class PendingProfiles { | 24 // callback). |
| 25 class DefaultProfileProcessor { |
| 25 public: | 26 public: |
| 26 ~PendingProfiles(); | 27 using CompletedCallback = StackSamplingProfiler::CompletedCallback; |
| 27 | 28 |
| 28 static PendingProfiles* GetInstance(); | 29 ~DefaultProfileProcessor(); |
| 29 | 30 |
| 30 // Appends |profiles| to |profiles_|. This function may be called on any | 31 static DefaultProfileProcessor* GetInstance(); |
| 31 // thread. | 32 |
| 32 void AppendProfiles( | 33 // Sets the callback to use for processing profiles captured without a |
| 33 const std::vector<StackSamplingProfiler::CallStackProfile>& profiles); | 34 // per-profiler completed callback. Pending completed profiles are stored in |
| 35 // this object until a non-null callback is provided here. This function is |
| 36 // thread-safe. |
| 37 void SetCompletedCallback(CompletedCallback callback); |
| 38 |
| 39 // Processes |profiles|. This function is thread safe. |
| 40 void ProcessProfiles( |
| 41 const StackSamplingProfiler::CallStackProfiles& profiles); |
| 42 |
| 43 private: |
| 44 friend struct DefaultSingletonTraits<DefaultProfileProcessor>; |
| 45 |
| 46 DefaultProfileProcessor(); |
| 34 | 47 |
| 35 // Copies the pending profiles from |profiles_| into |profiles|, and clears | 48 // Copies the pending profiles from |profiles_| into |profiles|, and clears |
| 36 // |profiles_|. This function may be called on any thread. | 49 // |profiles_|. This function may be called on any thread. |
| 37 void GetAndClearPendingProfiles( | 50 void GetAndClearPendingProfiles( |
| 38 std::vector<StackSamplingProfiler::CallStackProfile>* profiles); | 51 StackSamplingProfiler::CallStackProfiles* profiles); |
| 39 | 52 |
| 40 private: | 53 // Gets the current completed callback, with proper locking. |
| 41 friend struct DefaultSingletonTraits<PendingProfiles>; | 54 CompletedCallback GetCompletedCallback() const; |
| 42 | 55 |
| 43 PendingProfiles(); | 56 mutable Lock callback_lock_; |
| 57 CompletedCallback default_completed_callback_; |
| 44 | 58 |
| 45 Lock profiles_lock_; | 59 Lock profiles_lock_; |
| 46 std::vector<StackSamplingProfiler::CallStackProfile> profiles_; | 60 StackSamplingProfiler::CallStackProfiles profiles_; |
| 47 | 61 |
| 48 DISALLOW_COPY_AND_ASSIGN(PendingProfiles); | 62 DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor); |
| 49 }; | 63 }; |
| 50 | 64 |
| 51 PendingProfiles::PendingProfiles() {} | 65 DefaultProfileProcessor::~DefaultProfileProcessor() {} |
| 52 | |
| 53 PendingProfiles::~PendingProfiles() {} | |
| 54 | 66 |
| 55 // static | 67 // static |
| 56 PendingProfiles* PendingProfiles::GetInstance() { | 68 DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() { |
| 57 return Singleton<PendingProfiles>::get(); | 69 return Singleton<DefaultProfileProcessor>::get(); |
| 58 } | 70 } |
| 59 | 71 |
| 60 void PendingProfiles::AppendProfiles( | 72 void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) { |
| 61 const std::vector<StackSamplingProfiler::CallStackProfile>& profiles) { | 73 { |
| 62 AutoLock scoped_lock(profiles_lock_); | 74 AutoLock scoped_lock(callback_lock_); |
| 63 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); | 75 default_completed_callback_ = callback; |
| 76 } |
| 77 |
| 78 if (!callback.is_null()) { |
| 79 // Provide any pending profiles to the callback immediately. |
| 80 StackSamplingProfiler::CallStackProfiles profiles; |
| 81 GetAndClearPendingProfiles(&profiles); |
| 82 if (!profiles.empty()) |
| 83 callback.Run(profiles); |
| 84 } |
| 64 } | 85 } |
| 65 | 86 |
| 66 void PendingProfiles::GetAndClearPendingProfiles( | 87 void DefaultProfileProcessor::ProcessProfiles( |
| 67 std::vector<StackSamplingProfiler::CallStackProfile>* profiles) { | 88 const StackSamplingProfiler::CallStackProfiles& profiles) { |
| 89 CompletedCallback callback = GetCompletedCallback(); |
| 90 |
| 91 // Store pending profiles if we don't have a valid callback. |
| 92 if (!callback.is_null()) { |
| 93 callback.Run(profiles); |
| 94 } else { |
| 95 AutoLock scoped_lock(profiles_lock_); |
| 96 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); |
| 97 } |
| 98 } |
| 99 |
| 100 DefaultProfileProcessor::DefaultProfileProcessor() {} |
| 101 |
| 102 void DefaultProfileProcessor::GetAndClearPendingProfiles( |
| 103 StackSamplingProfiler::CallStackProfiles* profiles) { |
| 68 profiles->clear(); | 104 profiles->clear(); |
| 69 | 105 |
| 70 AutoLock scoped_lock(profiles_lock_); | 106 AutoLock scoped_lock(profiles_lock_); |
| 71 profiles_.swap(*profiles); | 107 profiles_.swap(*profiles); |
| 72 } | 108 } |
| 109 DefaultProfileProcessor::CompletedCallback |
| 110 DefaultProfileProcessor::GetCompletedCallback() const { |
| 111 AutoLock scoped_lock(callback_lock_); |
| 112 return default_completed_callback_; |
| 113 } |
| 73 | 114 |
| 74 } // namespace | 115 } // namespace |
| 75 | 116 |
| 76 // StackSamplingProfiler::Module ---------------------------------------------- | 117 // StackSamplingProfiler::Module ---------------------------------------------- |
| 77 | 118 |
| 78 StackSamplingProfiler::Module::Module() : base_address(nullptr) {} | 119 StackSamplingProfiler::Module::Module() : base_address(nullptr) {} |
| 79 StackSamplingProfiler::Module::Module(const void* base_address, | 120 StackSamplingProfiler::Module::Module(const void* base_address, |
| 80 const std::string& id, | 121 const std::string& id, |
| 81 const FilePath& filename) | 122 const FilePath& filename) |
| 82 : base_address(base_address), id(id), filename(filename) {} | 123 : base_address(base_address), id(id), filename(filename) {} |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 burst_interval(TimeDelta::FromMilliseconds(10000)), | 243 burst_interval(TimeDelta::FromMilliseconds(10000)), |
| 203 samples_per_burst(300), | 244 samples_per_burst(300), |
| 204 sampling_interval(TimeDelta::FromMilliseconds(100)), | 245 sampling_interval(TimeDelta::FromMilliseconds(100)), |
| 205 preserve_sample_ordering(false) { | 246 preserve_sample_ordering(false) { |
| 206 } | 247 } |
| 207 | 248 |
| 208 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, | 249 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
| 209 const SamplingParams& params) | 250 const SamplingParams& params) |
| 210 : thread_id_(thread_id), params_(params) {} | 251 : thread_id_(thread_id), params_(params) {} |
| 211 | 252 |
| 212 StackSamplingProfiler::~StackSamplingProfiler() {} | 253 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
| 254 const SamplingParams& params, |
| 255 CompletedCallback callback) |
| 256 : thread_id_(thread_id), params_(params), completed_callback_(callback) {} |
| 257 |
| 258 StackSamplingProfiler::~StackSamplingProfiler() { |
| 259 Stop(); |
| 260 if (!sampling_thread_handle_.is_null()) |
| 261 PlatformThread::Join(sampling_thread_handle_); |
| 262 } |
| 213 | 263 |
| 214 void StackSamplingProfiler::Start() { | 264 void StackSamplingProfiler::Start() { |
| 215 scoped_ptr<NativeStackSampler> native_sampler = | 265 scoped_ptr<NativeStackSampler> native_sampler = |
| 216 NativeStackSampler::Create(thread_id_); | 266 NativeStackSampler::Create(thread_id_); |
| 217 if (!native_sampler) | 267 if (!native_sampler) |
| 218 return; | 268 return; |
| 219 | 269 |
| 270 CompletedCallback callback = |
| 271 !completed_callback_.is_null() ? completed_callback_ : |
| 272 Bind(&DefaultProfileProcessor::ProcessProfiles, |
| 273 Unretained(DefaultProfileProcessor::GetInstance())); |
| 220 sampling_thread_.reset( | 274 sampling_thread_.reset( |
| 221 new SamplingThread( | 275 new SamplingThread(native_sampler.Pass(), params_, callback)); |
| 222 native_sampler.Pass(), params_, | 276 if (!PlatformThread::Create(0, sampling_thread_.get(), |
| 223 (custom_completed_callback_.is_null() ? | 277 &sampling_thread_handle_)) |
| 224 Bind(&PendingProfiles::AppendProfiles, | |
| 225 Unretained(PendingProfiles::GetInstance())) : | |
| 226 custom_completed_callback_))); | |
| 227 if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get())) | |
| 228 sampling_thread_.reset(); | 278 sampling_thread_.reset(); |
| 229 } | 279 } |
| 230 | 280 |
| 231 void StackSamplingProfiler::Stop() { | 281 void StackSamplingProfiler::Stop() { |
| 232 if (sampling_thread_) | 282 if (sampling_thread_) |
| 233 sampling_thread_->Stop(); | 283 sampling_thread_->Stop(); |
| 234 } | 284 } |
| 235 | 285 |
| 236 // static | 286 // static |
| 237 void StackSamplingProfiler::GetPendingProfiles(CallStackProfiles* profiles) { | 287 void StackSamplingProfiler::SetDefaultCompletedCallback( |
| 238 PendingProfiles::GetInstance()->GetAndClearPendingProfiles(profiles); | 288 CompletedCallback callback) { |
| 289 DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback); |
| 239 } | 290 } |
| 240 | 291 |
| 241 // StackSamplingProfiler::Frame global functions ------------------------------ | 292 // StackSamplingProfiler::Frame global functions ------------------------------ |
| 242 | 293 |
| 243 bool operator==(const StackSamplingProfiler::Frame &a, | 294 bool operator==(const StackSamplingProfiler::Frame &a, |
| 244 const StackSamplingProfiler::Frame &b) { | 295 const StackSamplingProfiler::Frame &b) { |
| 245 return a.instruction_pointer == b.instruction_pointer && | 296 return a.instruction_pointer == b.instruction_pointer && |
| 246 a.module_index == b.module_index; | 297 a.module_index == b.module_index; |
| 247 } | 298 } |
| 248 | 299 |
| 249 bool operator<(const StackSamplingProfiler::Frame &a, | 300 bool operator<(const StackSamplingProfiler::Frame &a, |
| 250 const StackSamplingProfiler::Frame &b) { | 301 const StackSamplingProfiler::Frame &b) { |
| 251 return (a.module_index < b.module_index) || | 302 return (a.module_index < b.module_index) || |
| 252 (a.module_index == b.module_index && | 303 (a.module_index == b.module_index && |
| 253 a.instruction_pointer < b.instruction_pointer); | 304 a.instruction_pointer < b.instruction_pointer); |
| 254 } | 305 } |
| 255 | 306 |
| 256 } // namespace base | 307 } // namespace base |
| OLD | NEW |