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 |