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/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
13 #include "base/synchronization/waitable_event.h" | 13 #include "base/synchronization/waitable_event.h" |
14 #include "base/timer/elapsed_timer.h" | 14 #include "base/timer/elapsed_timer.h" |
15 | 15 |
16 template <typename T> struct DefaultSingletonTraits; | 16 template <typename T> struct DefaultSingletonTraits; |
17 | 17 |
18 namespace base { | 18 namespace base { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 // Thread-safe singleton class that stores collected profiles waiting to be | 22 // Singleton class responsible for providing the default processing for profiles |
23 // 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 ~PendingProfiles(); | |
28 | 28 |
29 static PendingProfiles* GetInstance(); | 29 DefaultProfileProcessor(); |
| 30 ~DefaultProfileProcessor(); |
30 | 31 |
31 // Appends |profiles|. This function is thread safe. | 32 static DefaultProfileProcessor* GetInstance(); |
32 void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles); | 33 |
33 // Gets the pending profiles into *|profiles|. This function is thread safe. | 34 // Sets the callback to use for processing profiles captured without a |
| 35 // per-profiler completed callback. Pending completed profiles are stored in |
| 36 // this object until a non-null callback is provided here. This function is |
| 37 // thread-safe. |
| 38 void SetCompletedCallback(CompletedCallback callback); |
| 39 |
| 40 // Processes |profiles|. This function is thread safe. |
| 41 void ProcessProfiles( |
| 42 const std::vector<StackSamplingProfiler::Profile>& profiles); |
| 43 |
| 44 private: |
| 45 // Gets the pending profiles into *|profiles|, with proper locking. |
34 void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles); | 46 void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles); |
35 | 47 |
36 private: | 48 // Gets the current completed callback, with proper locking. |
| 49 CompletedCallback GetCompletedCallback() const; |
| 50 |
| 51 mutable Lock callback_lock_; |
| 52 CompletedCallback default_completed_callback_; |
| 53 |
37 Lock profiles_lock_; | 54 Lock profiles_lock_; |
38 std::vector<StackSamplingProfiler::Profile> profiles_; | 55 std::vector<StackSamplingProfiler::Profile> profiles_; |
39 | 56 |
40 DISALLOW_COPY_AND_ASSIGN(PendingProfiles); | 57 DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor); |
41 }; | 58 }; |
42 | 59 |
43 PendingProfiles::PendingProfiles() {} | 60 DefaultProfileProcessor::DefaultProfileProcessor() {} |
44 | 61 |
45 PendingProfiles::~PendingProfiles() {} | 62 DefaultProfileProcessor::~DefaultProfileProcessor() {} |
46 | 63 |
47 // static | 64 // static |
48 PendingProfiles* PendingProfiles::GetInstance() { | 65 DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() { |
49 return Singleton<PendingProfiles>::get(); | 66 return Singleton<DefaultProfileProcessor>::get(); |
50 } | 67 } |
51 | 68 |
52 void PendingProfiles::PutProfiles( | 69 void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) { |
53 const std::vector<StackSamplingProfiler::Profile>& profiles) { | 70 { |
54 AutoLock scoped_lock(profiles_lock_); | 71 AutoLock scoped_lock(callback_lock_); |
55 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); | 72 default_completed_callback_ = callback; |
| 73 } |
| 74 |
| 75 if (!callback.is_null()) { |
| 76 // Provide any pending profiles to the callback immediately. |
| 77 std::vector<StackSamplingProfiler::Profile> profiles; |
| 78 GetProfiles(&profiles); |
| 79 if (!profiles.empty()) |
| 80 callback.Run(profiles); |
| 81 } |
56 } | 82 } |
57 | 83 |
58 void PendingProfiles::GetProfiles( | 84 void DefaultProfileProcessor::ProcessProfiles( |
| 85 const std::vector<StackSamplingProfiler::Profile>& profiles) { |
| 86 CompletedCallback callback = GetCompletedCallback(); |
| 87 |
| 88 // Store pending profiles if we don't have a valid callback. |
| 89 if (!callback.is_null()) { |
| 90 callback.Run(profiles); |
| 91 } else { |
| 92 AutoLock scoped_lock(profiles_lock_); |
| 93 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); |
| 94 } |
| 95 } |
| 96 |
| 97 void DefaultProfileProcessor::GetProfiles( |
59 std::vector<StackSamplingProfiler::Profile>* profiles) { | 98 std::vector<StackSamplingProfiler::Profile>* profiles) { |
60 profiles->clear(); | 99 profiles->clear(); |
61 | 100 |
62 AutoLock scoped_lock(profiles_lock_); | 101 AutoLock scoped_lock(profiles_lock_); |
63 profiles_.swap(*profiles); | 102 profiles_.swap(*profiles); |
64 } | 103 } |
| 104 |
| 105 DefaultProfileProcessor::CompletedCallback |
| 106 DefaultProfileProcessor::GetCompletedCallback() const { |
| 107 AutoLock scoped_lock(callback_lock_); |
| 108 return default_completed_callback_; |
| 109 } |
65 } // namespace | 110 } // namespace |
66 | 111 |
67 StackSamplingProfiler::Module::Module() : base_address(nullptr) {} | 112 StackSamplingProfiler::Module::Module() : base_address(nullptr) {} |
68 StackSamplingProfiler::Module::Module(const void* base_address, | 113 StackSamplingProfiler::Module::Module(const void* base_address, |
69 const std::string& id, | 114 const std::string& id, |
70 const FilePath& filename) | 115 const FilePath& filename) |
71 : base_address(base_address), id(id), filename(filename) {} | 116 : base_address(base_address), id(id), filename(filename) {} |
72 | 117 |
73 StackSamplingProfiler::Module::~Module() {} | 118 StackSamplingProfiler::Module::~Module() {} |
74 | 119 |
75 StackSamplingProfiler::Frame::Frame() | 120 StackSamplingProfiler::Frame::Frame() |
76 : instruction_pointer(nullptr), | 121 : instruction_pointer(nullptr), |
77 module_index(-1) {} | 122 module_index(-1) {} |
78 | 123 |
79 StackSamplingProfiler::Frame::Frame(const void* instruction_pointer, | 124 StackSamplingProfiler::Frame::Frame(const void* instruction_pointer, |
80 int module_index) | 125 int module_index) |
81 : instruction_pointer(instruction_pointer), | 126 : instruction_pointer(instruction_pointer), |
82 module_index(module_index) {} | 127 module_index(module_index) {} |
83 | 128 |
84 StackSamplingProfiler::Frame::~Frame() {} | 129 StackSamplingProfiler::Frame::~Frame() {} |
85 | 130 |
86 StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {} | 131 StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {} |
87 | 132 |
88 StackSamplingProfiler::Profile::~Profile() {} | 133 StackSamplingProfiler::Profile::~Profile() {} |
89 | 134 |
90 class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { | 135 class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { |
91 public: | 136 public: |
92 // Samples stacks using |native_sampler|. When complete, invokes | 137 // Samples stacks using |native_sampler|. When complete, invokes |
93 // |profiles_callback| with the collected profiles. |profiles_callback| must | 138 // |completed_callback| with the collected profiles. |completed_callback| must |
94 // be thread-safe and may consume the contents of the vector. | 139 // be thread-safe. |
95 SamplingThread( | 140 SamplingThread(scoped_ptr<NativeStackSampler> native_sampler, |
96 scoped_ptr<NativeStackSampler> native_sampler, | 141 const SamplingParams& params, |
97 const SamplingParams& params, | 142 CompletedCallback completed_callback); |
98 Callback<void(const std::vector<Profile>&)> completed_callback); | |
99 ~SamplingThread() override; | 143 ~SamplingThread() override; |
100 | 144 |
101 // Implementation of PlatformThread::Delegate: | 145 // Implementation of PlatformThread::Delegate: |
102 void ThreadMain() override; | 146 void ThreadMain() override; |
103 | 147 |
104 void Stop(); | 148 void Stop(); |
105 | 149 |
106 private: | 150 private: |
107 // Collects a profile from a single burst. Returns true if the profile was | 151 // Collects a profile from a single burst. Returns true if the profile was |
108 // collected, or false if collection was stopped before it completed. | 152 // collected, or false if collection was stopped before it completed. |
109 bool CollectProfile(Profile* profile, TimeDelta* elapsed_time); | 153 bool CollectProfile(Profile* profile, TimeDelta* elapsed_time); |
110 // Collects profiles from all bursts, or until the sampling is stopped. If | 154 // Collects profiles from all bursts, or until the sampling is stopped. If |
111 // stopped before complete, |profiles| will contains only full bursts. | 155 // stopped before complete, |profiles| will contain only full bursts. |
112 void CollectProfiles(std::vector<Profile>* profiles); | 156 void CollectProfiles(std::vector<Profile>* profiles); |
113 | 157 |
114 scoped_ptr<NativeStackSampler> native_sampler_; | 158 scoped_ptr<NativeStackSampler> native_sampler_; |
115 | 159 |
116 const SamplingParams params_; | 160 const SamplingParams params_; |
117 | 161 |
118 WaitableEvent stop_event_; | 162 WaitableEvent stop_event_; |
119 | 163 |
120 Callback<void(const std::vector<Profile>&)> completed_callback_; | 164 CompletedCallback completed_callback_; |
121 | 165 |
122 DISALLOW_COPY_AND_ASSIGN(SamplingThread); | 166 DISALLOW_COPY_AND_ASSIGN(SamplingThread); |
123 }; | 167 }; |
124 | 168 |
125 StackSamplingProfiler::SamplingThread::SamplingThread( | 169 StackSamplingProfiler::SamplingThread::SamplingThread( |
126 scoped_ptr<NativeStackSampler> native_sampler, | 170 scoped_ptr<NativeStackSampler> native_sampler, |
127 const SamplingParams& params, | 171 const SamplingParams& params, |
128 Callback<void(const std::vector<Profile>&)> completed_callback) | 172 CompletedCallback completed_callback) |
129 : native_sampler_(native_sampler.Pass()), | 173 : native_sampler_(native_sampler.Pass()), |
130 params_(params), | 174 params_(params), |
131 stop_event_(false, false), | 175 stop_event_(false, false), |
132 completed_callback_(completed_callback) { | 176 completed_callback_(completed_callback) { |
133 } | 177 } |
134 | 178 |
135 StackSamplingProfiler::SamplingThread::~SamplingThread() {} | 179 StackSamplingProfiler::SamplingThread::~SamplingThread() {} |
136 | 180 |
137 void StackSamplingProfiler::SamplingThread::ThreadMain() { | 181 void StackSamplingProfiler::SamplingThread::ThreadMain() { |
138 PlatformThread::SetName("Chrome_SamplingProfilerThread"); | 182 PlatformThread::SetName("Chrome_SamplingProfilerThread"); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 burst_interval(TimeDelta::FromMilliseconds(10000)), | 258 burst_interval(TimeDelta::FromMilliseconds(10000)), |
215 samples_per_burst(300), | 259 samples_per_burst(300), |
216 sampling_interval(TimeDelta::FromMilliseconds(100)), | 260 sampling_interval(TimeDelta::FromMilliseconds(100)), |
217 preserve_sample_ordering(false) { | 261 preserve_sample_ordering(false) { |
218 } | 262 } |
219 | 263 |
220 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, | 264 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
221 const SamplingParams& params) | 265 const SamplingParams& params) |
222 : thread_id_(thread_id), params_(params) {} | 266 : thread_id_(thread_id), params_(params) {} |
223 | 267 |
224 StackSamplingProfiler::~StackSamplingProfiler() {} | 268 StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
| 269 const SamplingParams& params, |
| 270 CompletedCallback callback) |
| 271 : thread_id_(thread_id), params_(params), completed_callback_(callback) {} |
| 272 |
| 273 StackSamplingProfiler::~StackSamplingProfiler() { |
| 274 Stop(); |
| 275 if (!sampling_thread_handle_.is_null()) |
| 276 PlatformThread::Join(sampling_thread_handle_); |
| 277 } |
225 | 278 |
226 void StackSamplingProfiler::Start() { | 279 void StackSamplingProfiler::Start() { |
227 native_sampler_ = NativeStackSampler::Create(thread_id_); | 280 scoped_ptr<NativeStackSampler> native_sampler( |
228 if (!native_sampler_) | 281 NativeStackSampler::Create(thread_id_)); |
| 282 if (!native_sampler) |
229 return; | 283 return; |
230 | 284 |
| 285 CompletedCallback callback = |
| 286 !completed_callback_.is_null() ? completed_callback_ : |
| 287 Bind(&DefaultProfileProcessor::ProcessProfiles, |
| 288 Unretained(DefaultProfileProcessor::GetInstance())); |
| 289 |
231 sampling_thread_.reset( | 290 sampling_thread_.reset( |
232 new SamplingThread( | 291 new SamplingThread(native_sampler.Pass(), params_, callback)); |
233 native_sampler_.Pass(), params_, | 292 if (!PlatformThread::Create(0, sampling_thread_.get(), |
234 (custom_completed_callback_.is_null() ? | 293 &sampling_thread_handle_)) |
235 Bind(&PendingProfiles::PutProfiles, | |
236 Unretained(PendingProfiles::GetInstance())) : | |
237 custom_completed_callback_))); | |
238 if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get())) | |
239 LOG(ERROR) << "failed to create thread"; | 294 LOG(ERROR) << "failed to create thread"; |
240 } | 295 } |
241 | 296 |
242 void StackSamplingProfiler::Stop() { | 297 void StackSamplingProfiler::Stop() { |
243 if (sampling_thread_) | 298 if (sampling_thread_) |
244 sampling_thread_->Stop(); | 299 sampling_thread_->Stop(); |
245 } | 300 } |
246 | 301 |
247 // static | 302 // static |
248 void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) { | 303 void StackSamplingProfiler::SetDefaultCompletedCallback( |
249 PendingProfiles::GetInstance()->GetProfiles(profiles); | 304 CompletedCallback callback) { |
250 } | 305 DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback); |
251 | |
252 void StackSamplingProfiler::SetCustomCompletedCallback( | |
253 Callback<void(const std::vector<Profile>&)> callback) { | |
254 custom_completed_callback_ = callback; | |
255 } | 306 } |
256 | 307 |
257 bool operator==(const StackSamplingProfiler::Frame &a, | 308 bool operator==(const StackSamplingProfiler::Frame &a, |
258 const StackSamplingProfiler::Frame &b) { | 309 const StackSamplingProfiler::Frame &b) { |
259 return a.instruction_pointer == b.instruction_pointer && | 310 return a.instruction_pointer == b.instruction_pointer && |
260 a.module_index == b.module_index; | 311 a.module_index == b.module_index; |
261 } | 312 } |
262 | 313 |
263 bool operator<(const StackSamplingProfiler::Frame &a, | 314 bool operator<(const StackSamplingProfiler::Frame &a, |
264 const StackSamplingProfiler::Frame &b) { | 315 const StackSamplingProfiler::Frame &b) { |
265 return (a.module_index < b.module_index) || | 316 return (a.module_index < b.module_index) || |
266 (a.module_index == b.module_index && | 317 (a.module_index == b.module_index && |
267 a.instruction_pointer < b.instruction_pointer); | 318 a.instruction_pointer < b.instruction_pointer); |
268 } | 319 } |
269 | 320 |
270 } // namespace base | 321 } // namespace base |
OLD | NEW |