Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: base/profiler/stack_sampling_profiler.cc

Issue 1030923002: StackSamplingProfiler clean up (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkcr
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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;
Peter Kasting 2015/03/26 04:29:05 Is this necessary? I don't see a usage.
Mike Wittman 2015/03/27 22:42:01 No, since I include the relevant header. But I sho
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 // Thread-safe singleton class that stores collected profiles waiting to be
23 // processed. 23 // processed.
24 class PendingProfiles { 24 class PendingProfiles {
Peter Kasting 2015/03/26 04:29:06 Nit: Since you define several different classes in
Mike Wittman 2015/03/27 22:42:02 Done.
25 public: 25 public:
26 PendingProfiles(); 26 PendingProfiles();
27 ~PendingProfiles(); 27 ~PendingProfiles();
28 28
29 static PendingProfiles* GetInstance(); 29 static PendingProfiles* GetInstance();
30 30
31 // Appends |profiles|. This function is thread safe. 31 // Appends |profiles|. This function is thread safe.
Peter Kasting 2015/03/26 04:29:06 Nit: Maybe "Appends |profiles| to |profiles_|" or
Mike Wittman 2015/03/27 22:42:02 Done.
32 void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles); 32 void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles);
Peter Kasting 2015/03/26 04:29:06 Nit: "Put" seems like a vague verb here -- perhaps
Mike Wittman 2015/03/27 22:42:02 Done.
33 // Gets the pending profiles into *|profiles|. This function is thread safe. 33 // Gets the pending profiles into *|profiles|. This function is thread safe.
Peter Kasting 2015/03/26 04:29:05 Nit: Blank line above Consider using the same com
Mike Wittman 2015/03/27 22:42:01 Done.
34 void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles); 34 void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles);
35 35
36 private: 36 private:
37 Lock profiles_lock_; 37 Lock profiles_lock_;
38 std::vector<StackSamplingProfiler::Profile> profiles_; 38 std::vector<StackSamplingProfiler::Profile> profiles_;
39 39
40 DISALLOW_COPY_AND_ASSIGN(PendingProfiles); 40 DISALLOW_COPY_AND_ASSIGN(PendingProfiles);
41 }; 41 };
42 42
43 PendingProfiles::PendingProfiles() {} 43 PendingProfiles::PendingProfiles() {}
(...skipping 11 matching lines...) Expand all
55 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); 55 profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
56 } 56 }
57 57
58 void PendingProfiles::GetProfiles( 58 void PendingProfiles::GetProfiles(
59 std::vector<StackSamplingProfiler::Profile>* profiles) { 59 std::vector<StackSamplingProfiler::Profile>* profiles) {
60 profiles->clear(); 60 profiles->clear();
61 61
62 AutoLock scoped_lock(profiles_lock_); 62 AutoLock scoped_lock(profiles_lock_);
63 profiles_.swap(*profiles); 63 profiles_.swap(*profiles);
64 } 64 }
65 } // namespace 65 } // namespace
Peter Kasting 2015/03/26 04:29:06 Nit: Blank line above
Mike Wittman 2015/03/27 22:42:01 Done.
66 66
67 StackSamplingProfiler::Module::Module() : base_address(nullptr) {} 67 StackSamplingProfiler::Module::Module() : base_address(nullptr) {}
68 68
69 StackSamplingProfiler::Module::~Module() {} 69 StackSamplingProfiler::Module::~Module() {}
70 70
71 StackSamplingProfiler::Frame::Frame() 71 StackSamplingProfiler::Frame::Frame()
72 : instruction_pointer(nullptr), 72 : instruction_pointer(nullptr),
73 module_index(-1) {} 73 module_index(-1) {}
74 74
75 StackSamplingProfiler::Frame::~Frame() {} 75 StackSamplingProfiler::Frame::~Frame() {}
76 76
77 StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {} 77 StackSamplingProfiler::Profile::Profile() : preserve_sample_ordering(false) {}
78 78
79 StackSamplingProfiler::Profile::~Profile() {} 79 StackSamplingProfiler::Profile::~Profile() {}
80 80
81 class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { 81 class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
82 public: 82 public:
83 // Samples stacks using |native_sampler|. When complete, invokes 83 // Samples stacks using |native_sampler|. When complete, invokes
84 // |profiles_callback| with the collected profiles. |profiles_callback| must 84 // |profiles_callback| with the collected profiles. |profiles_callback| must
Peter Kasting 2015/03/26 04:29:06 Do you mean |completed_callback|?
Mike Wittman 2015/03/27 22:42:02 Yes, changed. Also removed the defunct last clause
85 // be thread-safe and may consume the contents of the vector. 85 // be thread-safe and may consume the contents of the vector.
86 SamplingThread( 86 SamplingThread(
87 scoped_ptr<NativeStackSampler> native_sampler, 87 scoped_ptr<NativeStackSampler> native_sampler,
88 const SamplingParams& params, 88 const SamplingParams& params,
89 Callback<void(const std::vector<Profile>&)> completed_callback); 89 Callback<void(const std::vector<Profile>&)> completed_callback);
90 ~SamplingThread() override; 90 ~SamplingThread() override;
91 91
92 // Implementation of PlatformThread::Delegate: 92 // Implementation of PlatformThread::Delegate:
Peter Kasting 2015/03/26 04:29:05 Nit: "Implementation of" is not really necessary
Mike Wittman 2015/03/27 22:42:02 Done.
93 void ThreadMain() override; 93 void ThreadMain() override;
94 94
95 void Stop(); 95 void Stop();
96 96
97 private: 97 private:
98 // Collects a profile from a single burst. Returns true if the profile was 98 // Collects a profile from a single burst. Returns true if the profile was
99 // collected, or false if collection was stopped before it completed. 99 // collected, or false if collection was stopped before it completed.
100 bool CollectProfile(Profile* profile, TimeDelta* elapsed_time); 100 bool CollectProfile(Profile* profile, TimeDelta* elapsed_time);
101 // Collects profiles from all bursts, or until the sampling is stopped. If 101 // Collects profiles from all bursts, or until the sampling is stopped. If
Peter Kasting 2015/03/26 04:29:06 Nit: Blank line above
Mike Wittman 2015/03/27 22:42:02 Done.
102 // stopped before complete, |profiles| will contains only full bursts. 102 // stopped before complete, |profiles| will contains only full bursts.
Peter Kasting 2015/03/26 04:29:05 contain
Mike Wittman 2015/03/27 22:42:02 Done.
103 void CollectProfiles(std::vector<Profile>* profiles); 103 void CollectProfiles(std::vector<Profile>* profiles);
104 104
105 scoped_ptr<NativeStackSampler> native_sampler_; 105 scoped_ptr<NativeStackSampler> native_sampler_;
106 106
Peter Kasting 2015/03/26 04:29:05 Nit: You can remove the blank line between two mem
Mike Wittman 2015/03/27 22:42:02 Done.
107 const SamplingParams params_; 107 const SamplingParams params_;
108 108
109 WaitableEvent stop_event_; 109 WaitableEvent stop_event_;
Peter Kasting 2015/03/26 04:29:06 At least this member probably deserves a comment a
Mike Wittman 2015/03/27 22:42:01 Done.
110 110
111 Callback<void(const std::vector<Profile>&)> completed_callback_; 111 Callback<void(const std::vector<Profile>&)> completed_callback_;
112 112
113 DISALLOW_COPY_AND_ASSIGN(SamplingThread); 113 DISALLOW_COPY_AND_ASSIGN(SamplingThread);
114 }; 114 };
115 115
116 StackSamplingProfiler::SamplingThread::SamplingThread( 116 StackSamplingProfiler::SamplingThread::SamplingThread(
117 scoped_ptr<NativeStackSampler> native_sampler, 117 scoped_ptr<NativeStackSampler> native_sampler,
118 const SamplingParams& params, 118 const SamplingParams& params,
119 Callback<void(const std::vector<Profile>&)> completed_callback) 119 Callback<void(const std::vector<Profile>&)> completed_callback)
(...skipping 13 matching lines...) Expand all
133 completed_callback_.Run(profiles); 133 completed_callback_.Run(profiles);
134 } 134 }
135 135
136 bool StackSamplingProfiler::SamplingThread::CollectProfile( 136 bool StackSamplingProfiler::SamplingThread::CollectProfile(
137 Profile* profile, 137 Profile* profile,
138 TimeDelta* elapsed_time) { 138 TimeDelta* elapsed_time) {
139 ElapsedTimer profile_timer; 139 ElapsedTimer profile_timer;
140 Profile current_profile; 140 Profile current_profile;
141 native_sampler_->ProfileRecordingStarting(&current_profile); 141 native_sampler_->ProfileRecordingStarting(&current_profile);
142 current_profile.sampling_period = params_.sampling_interval; 142 current_profile.sampling_period = params_.sampling_interval;
143 bool stopped_early = false; 143 bool stopped_early = false;
Peter Kasting 2015/03/26 04:29:05 Nit: I'm on the fence about this, but because you
Mike Wittman 2015/03/27 22:42:02 burst_completed is probably slightly better; updat
144 for (int i = 0; i < params_.samples_per_burst; ++i) { 144 for (int i = 0; i < params_.samples_per_burst; ++i) {
Peter Kasting 2015/03/26 04:29:05 If sampling takes too long/things are laggy/the sa
Mike Wittman 2015/03/27 22:42:02 At this point the goal for this functionality just
145 ElapsedTimer sample_timer; 145 ElapsedTimer sample_timer;
146 current_profile.samples.push_back(Sample()); 146 current_profile.samples.push_back(Sample());
147 native_sampler_->RecordStackSample(&current_profile.samples.back()); 147 native_sampler_->RecordStackSample(&current_profile.samples.back());
148 TimeDelta elapsed_sample_time = sample_timer.Elapsed(); 148 TimeDelta elapsed_sample_time = sample_timer.Elapsed();
149 if (i != params_.samples_per_burst - 1) { 149 if (i != params_.samples_per_burst - 1) {
Peter Kasting 2015/03/26 04:29:06 Super nitpicky nit: If you move this to the top of
Mike Wittman 2015/03/27 22:42:02 Done.
150 if (stop_event_.TimedWait( 150 if (stop_event_.TimedWait(
151 std::max(params_.sampling_interval - elapsed_sample_time, 151 std::max(params_.sampling_interval - elapsed_sample_time,
Peter Kasting 2015/03/26 04:29:06 If the elapsed time is greater than the sampling i
Mike Wittman 2015/03/27 22:42:02 Yes, that's exactly the reason. We could check sto
152 TimeDelta()))) { 152 TimeDelta()))) {
153 stopped_early = true; 153 stopped_early = true;
154 break; 154 break;
155 } 155 }
156 } 156 }
157 } 157 }
158 158
159 *elapsed_time = profile_timer.Elapsed(); 159 *elapsed_time = profile_timer.Elapsed();
160 current_profile.profile_duration = *elapsed_time; 160 current_profile.profile_duration = *elapsed_time;
161 native_sampler_->ProfileRecordingStopped(); 161 native_sampler_->ProfileRecordingStopped();
162 162
163 if (!stopped_early) 163 if (!stopped_early)
164 *profile = current_profile; 164 *profile = current_profile;
165 165
166 return !stopped_early; 166 return !stopped_early;
167 } 167 }
168 168
169 void StackSamplingProfiler::SamplingThread::CollectProfiles( 169 void StackSamplingProfiler::SamplingThread::CollectProfiles(
170 std::vector<Profile>* profiles) { 170 std::vector<Profile>* profiles) {
171 if (stop_event_.TimedWait(params_.initial_delay)) 171 if (stop_event_.TimedWait(params_.initial_delay))
172 return; 172 return;
173 173
174 for (int i = 0; i < params_.bursts; ++i) { 174 for (int i = 0; i < params_.bursts; ++i) {
Peter Kasting 2015/03/26 04:29:06 Both the questions in CollectProfile() above about
Mike Wittman 2015/03/27 22:42:02 Added a comment.
175 Profile profile; 175 Profile profile;
176 TimeDelta elapsed_profile_time; 176 TimeDelta elapsed_profile_time;
177 if (CollectProfile(&profile, &elapsed_profile_time)) 177 if (CollectProfile(&profile, &elapsed_profile_time))
Peter Kasting 2015/03/26 04:29:06 Nit: Slightly simpler, and parallel to the constru
Mike Wittman 2015/03/27 22:42:02 Done.
178 profiles->push_back(profile); 178 profiles->push_back(profile);
179 else 179 else
180 return; 180 return;
181 181
182 if (stop_event_.TimedWait( 182 if (stop_event_.TimedWait(
183 std::max(params_.burst_interval - elapsed_profile_time, 183 std::max(params_.burst_interval - elapsed_profile_time,
184 TimeDelta()))) 184 TimeDelta())))
185 return; 185 return;
186 } 186 }
187 } 187 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 return; 220 return;
221 221
222 sampling_thread_.reset( 222 sampling_thread_.reset(
223 new SamplingThread( 223 new SamplingThread(
224 native_sampler_.Pass(), params_, 224 native_sampler_.Pass(), params_,
225 (custom_completed_callback_.is_null() ? 225 (custom_completed_callback_.is_null() ?
226 Bind(&PendingProfiles::PutProfiles, 226 Bind(&PendingProfiles::PutProfiles,
227 Unretained(PendingProfiles::GetInstance())) : 227 Unretained(PendingProfiles::GetInstance())) :
228 custom_completed_callback_))); 228 custom_completed_callback_)));
229 if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get())) 229 if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get()))
230 LOG(ERROR) << "failed to create thread"; 230 LOG(ERROR) << "failed to create thread";
Peter Kasting 2015/03/26 04:29:06 Normally we avoid LOG statements, since they bloat
Mike Wittman 2015/03/27 22:42:02 I agree LOG is not a good approach here. The desir
231 } 231 }
232 232
233 void StackSamplingProfiler::Stop() { 233 void StackSamplingProfiler::Stop() {
234 if (sampling_thread_) 234 if (sampling_thread_)
235 sampling_thread_->Stop(); 235 sampling_thread_->Stop();
236 } 236 }
237 237
238 // static 238 // static
239 void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) { 239 void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) {
240 PendingProfiles::GetInstance()->GetProfiles(profiles); 240 PendingProfiles::GetInstance()->GetProfiles(profiles);
241 } 241 }
242 242
243 void StackSamplingProfiler::SetCustomCompletedCallback( 243 void StackSamplingProfiler::SetCustomCompletedCallback(
244 Callback<void(const std::vector<Profile>&)> callback) { 244 Callback<void(const std::vector<Profile>&)> callback) {
245 custom_completed_callback_ = callback; 245 custom_completed_callback_ = callback;
Peter Kasting 2015/03/26 04:29:06 This sort of simple setter should probably be inli
Mike Wittman 2015/03/27 22:42:02 Done. This function used to have more logic, which
246 } 246 }
247 247
248 bool operator==(const StackSamplingProfiler::Frame &a, 248 bool operator==(const StackSamplingProfiler::Frame &a,
249 const StackSamplingProfiler::Frame &b) { 249 const StackSamplingProfiler::Frame &b) {
250 return a.instruction_pointer == b.instruction_pointer && 250 return a.instruction_pointer == b.instruction_pointer &&
251 a.module_index == b.module_index; 251 a.module_index == b.module_index;
252 } 252 }
253 253
254 bool operator<(const StackSamplingProfiler::Frame &a, 254 bool operator<(const StackSamplingProfiler::Frame &a,
255 const StackSamplingProfiler::Frame &b) { 255 const StackSamplingProfiler::Frame &b) {
256 return (a.module_index < b.module_index) || 256 return (a.module_index < b.module_index) ||
257 (a.module_index == b.module_index && 257 (a.module_index == b.module_index &&
258 a.instruction_pointer < b.instruction_pointer); 258 a.instruction_pointer < b.instruction_pointer);
259 } 259 }
260 260
261 } // namespace base 261 } // namespace base
262
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698