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

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

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: abandon generator for on-the-fly Profiles creation Created 4 years 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 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 void AsyncRunner::RunCallbackAndDeleteInstance( 75 void AsyncRunner::RunCallbackAndDeleteInstance(
76 std::unique_ptr<AsyncRunner> object_to_be_deleted, 76 std::unique_ptr<AsyncRunner> object_to_be_deleted,
77 const StackSamplingProfiler::CompletedCallback& callback, 77 const StackSamplingProfiler::CompletedCallback& callback,
78 scoped_refptr<SingleThreadTaskRunner> task_runner, 78 scoped_refptr<SingleThreadTaskRunner> task_runner,
79 StackSamplingProfiler::CallStackProfiles profiles) { 79 StackSamplingProfiler::CallStackProfiles profiles) {
80 callback.Run(std::move(profiles)); 80 callback.Run(std::move(profiles));
81 // Delete the instance on the original calling thread. 81 // Delete the instance on the original calling thread.
82 task_runner->DeleteSoon(FROM_HERE, object_to_be_deleted.release()); 82 task_runner->DeleteSoon(FROM_HERE, object_to_be_deleted.release());
83 } 83 }
84 84
85 void ChangeAtomicFlags(subtle::Atomic32* flags,
86 subtle::Atomic32 set,
87 subtle::Atomic32 clear) {
88 DCHECK(set != 0 || clear != 0);
89 DCHECK_EQ(0, set & clear);
90
91 subtle::Atomic32 bits = subtle::NoBarrier_Load(flags);
92 while (true) {
93 subtle::Atomic32 existing =
94 subtle::NoBarrier_CompareAndSwap(flags, bits, (bits | set) & ~clear);
95 if (existing == bits)
96 break;
97 bits = existing;
98 }
99 }
100
85 } // namespace 101 } // namespace
86 102
87 // StackSamplingProfiler::Module ---------------------------------------------- 103 // StackSamplingProfiler::Module ----------------------------------------------
88 104
89 StackSamplingProfiler::Module::Module() : base_address(0u) {} 105 StackSamplingProfiler::Module::Module() : base_address(0u) {}
90 StackSamplingProfiler::Module::Module(uintptr_t base_address, 106 StackSamplingProfiler::Module::Module(uintptr_t base_address,
91 const std::string& id, 107 const std::string& id,
92 const FilePath& filename) 108 const FilePath& filename)
93 : base_address(base_address), id(id), filename(filename) {} 109 : base_address(base_address), id(id), filename(filename) {}
94 110
95 StackSamplingProfiler::Module::~Module() {} 111 StackSamplingProfiler::Module::~Module() {}
96 112
97 // StackSamplingProfiler::Frame ----------------------------------------------- 113 // StackSamplingProfiler::Frame -----------------------------------------------
98 114
99 StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer, 115 StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer,
100 size_t module_index) 116 size_t module_index)
101 : instruction_pointer(instruction_pointer), module_index(module_index) {} 117 : instruction_pointer(instruction_pointer), module_index(module_index) {}
102 118
103 StackSamplingProfiler::Frame::~Frame() {} 119 StackSamplingProfiler::Frame::~Frame() {}
104 120
105 StackSamplingProfiler::Frame::Frame() 121 StackSamplingProfiler::Frame::Frame()
106 : instruction_pointer(0), module_index(kUnknownModuleIndex) { 122 : instruction_pointer(0), module_index(kUnknownModuleIndex) {
107 } 123 }
108 124
125 // StackSamplingProfiler::Sample ----------------------------------------------
126
127 StackSamplingProfiler::Sample::Sample() {}
128
129 StackSamplingProfiler::Sample::Sample(const Sample& sample) = default;
130
131 StackSamplingProfiler::Sample::~Sample() {}
132
133 StackSamplingProfiler::Sample::Sample(const Frame& frame) {
134 frames.push_back(std::move(frame));
135 }
136
137 StackSamplingProfiler::Sample::Sample(const std::vector<Frame>& frames)
138 : frames(frames) {}
139
109 // StackSamplingProfiler::CallStackProfile ------------------------------------ 140 // StackSamplingProfiler::CallStackProfile ------------------------------------
110 141
111 StackSamplingProfiler::CallStackProfile::CallStackProfile() {} 142 StackSamplingProfiler::CallStackProfile::CallStackProfile() {}
112 143
113 StackSamplingProfiler::CallStackProfile::CallStackProfile( 144 StackSamplingProfiler::CallStackProfile::CallStackProfile(
114 CallStackProfile&& other) = default; 145 CallStackProfile&& other) = default;
115 146
116 StackSamplingProfiler::CallStackProfile::~CallStackProfile() {} 147 StackSamplingProfiler::CallStackProfile::~CallStackProfile() {}
117 148
118 StackSamplingProfiler::CallStackProfile& 149 StackSamplingProfiler::CallStackProfile&
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 return; 253 return;
223 } 254 }
224 } 255 }
225 256
226 void StackSamplingProfiler::SamplingThread::Stop() { 257 void StackSamplingProfiler::SamplingThread::Stop() {
227 stop_event_.Signal(); 258 stop_event_.Signal();
228 } 259 }
229 260
230 // StackSamplingProfiler ------------------------------------------------------ 261 // StackSamplingProfiler ------------------------------------------------------
231 262
263 subtle::Atomic32 StackSamplingProfiler::process_phases_ = 0;
264
232 StackSamplingProfiler::SamplingParams::SamplingParams() 265 StackSamplingProfiler::SamplingParams::SamplingParams()
233 : initial_delay(TimeDelta::FromMilliseconds(0)), 266 : initial_delay(TimeDelta::FromMilliseconds(0)),
234 bursts(1), 267 bursts(1),
235 burst_interval(TimeDelta::FromMilliseconds(10000)), 268 burst_interval(TimeDelta::FromMilliseconds(10000)),
236 samples_per_burst(300), 269 samples_per_burst(300),
237 sampling_interval(TimeDelta::FromMilliseconds(100)) { 270 sampling_interval(TimeDelta::FromMilliseconds(100)) {
238 } 271 }
239 272
240 StackSamplingProfiler::StackSamplingProfiler( 273 StackSamplingProfiler::StackSamplingProfiler(
241 PlatformThreadId thread_id, 274 PlatformThreadId thread_id,
(...skipping 23 matching lines...) Expand all
265 const CompletedCallback& callback) { 298 const CompletedCallback& callback) {
266 CHECK(ThreadTaskRunnerHandle::Get()); 299 CHECK(ThreadTaskRunnerHandle::Get());
267 AsyncRunner::Run(thread_id, params, callback); 300 AsyncRunner::Run(thread_id, params, callback);
268 } 301 }
269 302
270 void StackSamplingProfiler::Start() { 303 void StackSamplingProfiler::Start() {
271 if (completed_callback_.is_null()) 304 if (completed_callback_.is_null())
272 return; 305 return;
273 306
274 std::unique_ptr<NativeStackSampler> native_sampler = 307 std::unique_ptr<NativeStackSampler> native_sampler =
275 NativeStackSampler::Create(thread_id_, test_delegate_); 308 NativeStackSampler::Create(thread_id_, &RecordAnnotations,
309 test_delegate_);
276 if (!native_sampler) 310 if (!native_sampler)
277 return; 311 return;
278 312
279 sampling_thread_.reset(new SamplingThread(std::move(native_sampler), params_, 313 sampling_thread_.reset(new SamplingThread(std::move(native_sampler), params_,
280 completed_callback_)); 314 completed_callback_));
281 if (!PlatformThread::Create(0, sampling_thread_.get(), 315 if (!PlatformThread::Create(0, sampling_thread_.get(),
282 &sampling_thread_handle_)) 316 &sampling_thread_handle_))
283 sampling_thread_.reset(); 317 sampling_thread_.reset();
284 } 318 }
285 319
286 void StackSamplingProfiler::Stop() { 320 void StackSamplingProfiler::Stop() {
287 if (sampling_thread_) 321 if (sampling_thread_)
288 sampling_thread_->Stop(); 322 sampling_thread_->Stop();
289 } 323 }
290 324
325 // static
326 void StackSamplingProfiler::SetProcessPhase(int phase) {
327 DCHECK_LE(0, phase);
328 DCHECK_GT(static_cast<int>(sizeof(process_phases_) * 8), phase);
329 DCHECK_EQ(0, subtle::NoBarrier_Load(&process_phases_) & (1 << phase));
330 ChangeAtomicFlags(&process_phases_, 1 << phase, 0);
331 }
332
333 // static
334 void StackSamplingProfiler::ResetAnnotationsForTesting() {
335 subtle::NoBarrier_Store(&process_phases_, 0u);
336 }
337
338 // static
339 void StackSamplingProfiler::RecordAnnotations(Sample* sample) {
340 // The code inside this method must not do anything that could acquire a
341 // mutex, including allocating memory (which includes LOG messages) because
342 // that mutex could be held by a stopped thread, thus resulting in deadlock.
343 sample->process_phases = subtle::NoBarrier_Load(&process_phases_);
344 }
345
291 // StackSamplingProfiler::Frame global functions ------------------------------ 346 // StackSamplingProfiler::Frame global functions ------------------------------
292 347
293 bool operator==(const StackSamplingProfiler::Module& a, 348 bool operator==(const StackSamplingProfiler::Module& a,
294 const StackSamplingProfiler::Module& b) { 349 const StackSamplingProfiler::Module& b) {
295 return a.base_address == b.base_address && a.id == b.id && 350 return a.base_address == b.base_address && a.id == b.id &&
296 a.filename == b.filename; 351 a.filename == b.filename;
297 } 352 }
298 353
354 bool operator==(const StackSamplingProfiler::Sample& a,
355 const StackSamplingProfiler::Sample& b) {
356 return a.process_phases == b.process_phases && a.frames == b.frames;
357 }
358
359 bool operator!=(const StackSamplingProfiler::Sample& a,
360 const StackSamplingProfiler::Sample& b) {
361 return !(a == b);
362 }
363
364 bool operator<(const StackSamplingProfiler::Sample& a,
365 const StackSamplingProfiler::Sample& b) {
366 if (a.process_phases < b.process_phases)
367 return true;
368 if (a.process_phases > b.process_phases)
369 return false;
370
371 return a.frames < b.frames;
372 }
373
299 bool operator==(const StackSamplingProfiler::Frame &a, 374 bool operator==(const StackSamplingProfiler::Frame &a,
300 const StackSamplingProfiler::Frame &b) { 375 const StackSamplingProfiler::Frame &b) {
301 return a.instruction_pointer == b.instruction_pointer && 376 return a.instruction_pointer == b.instruction_pointer &&
302 a.module_index == b.module_index; 377 a.module_index == b.module_index;
303 } 378 }
304 379
305 bool operator<(const StackSamplingProfiler::Frame &a, 380 bool operator<(const StackSamplingProfiler::Frame &a,
306 const StackSamplingProfiler::Frame &b) { 381 const StackSamplingProfiler::Frame &b) {
307 return (a.module_index < b.module_index) || 382 return (a.module_index < b.module_index) ||
308 (a.module_index == b.module_index && 383 (a.module_index == b.module_index &&
309 a.instruction_pointer < b.instruction_pointer); 384 a.instruction_pointer < b.instruction_pointer);
310 } 385 }
311 386
312 } // namespace base 387 } // namespace base
OLDNEW
« no previous file with comments | « base/profiler/stack_sampling_profiler.h ('k') | base/profiler/stack_sampling_profiler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698