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

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

Issue 2927593002: Make stack sampling profiler sample beyond startup. (Closed)
Patch Set: Temporary LOG statements for debugging. Created 3 years, 5 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 #include <map> 8 #include <map>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 13 matching lines...) Expand all
24 #include "base/threading/thread_restrictions.h" 24 #include "base/threading/thread_restrictions.h"
25 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/timer/elapsed_timer.h" 26 #include "base/timer/elapsed_timer.h"
27 27
28 namespace base { 28 namespace base {
29 29
30 namespace { 30 namespace {
31 31
32 // This value is used when there is no collection in progress and thus no ID 32 // This value is used when there is no collection in progress and thus no ID
33 // for referencing the active collection to the SamplingThread. 33 // for referencing the active collection to the SamplingThread.
34 const int NULL_COLLECTION_ID = -1; 34 const int NULL_PROFILER_ID = -1;
35 35
36 void ChangeAtomicFlags(subtle::Atomic32* flags, 36 void ChangeAtomicFlags(subtle::Atomic32* flags,
37 subtle::Atomic32 set, 37 subtle::Atomic32 set,
38 subtle::Atomic32 clear) { 38 subtle::Atomic32 clear) {
39 DCHECK(set != 0 || clear != 0); 39 DCHECK(set != 0 || clear != 0);
40 DCHECK_EQ(0, set & clear); 40 DCHECK_EQ(0, set & clear);
41 41
42 subtle::Atomic32 bits = subtle::NoBarrier_Load(flags); 42 subtle::Atomic32 bits = subtle::NoBarrier_Load(flags);
43 while (true) { 43 while (true) {
44 subtle::Atomic32 existing = 44 subtle::Atomic32 existing =
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 static void ShutdownAssumingIdle(bool simulate_intervening_add); 132 static void ShutdownAssumingIdle(bool simulate_intervening_add);
133 133
134 private: 134 private:
135 // Calls the sampling threads ShutdownTask and then signals an event. 135 // Calls the sampling threads ShutdownTask and then signals an event.
136 static void ShutdownTaskAndSignalEvent(SamplingThread* sampler, 136 static void ShutdownTaskAndSignalEvent(SamplingThread* sampler,
137 int add_events, 137 int add_events,
138 WaitableEvent* event); 138 WaitableEvent* event);
139 }; 139 };
140 140
141 struct CollectionContext { 141 struct CollectionContext {
142 CollectionContext(PlatformThreadId target, 142 CollectionContext(int profiler_id,
143 PlatformThreadId target,
143 const SamplingParams& params, 144 const SamplingParams& params,
144 const CompletedCallback& callback, 145 const CompletedCallback& callback,
145 WaitableEvent* finished, 146 WaitableEvent* finished,
146 std::unique_ptr<NativeStackSampler> sampler) 147 std::unique_ptr<NativeStackSampler> sampler)
147 : collection_id(next_collection_id_.GetNext()), 148 : profiler_id(profiler_id),
148 target(target), 149 target(target),
149 params(params), 150 params(params),
150 callback(callback), 151 callback(callback),
151 finished(finished), 152 finished(finished),
152 native_sampler(std::move(sampler)) {} 153 native_sampler(std::move(sampler)) {}
153 ~CollectionContext() {} 154 ~CollectionContext() {}
154 155
155 // An identifier for this collection, used to uniquely identify it to 156 // An identifier for the profiler associated with this collection, used to
156 // outside interests. 157 // uniquely identify the collection to outside interests.
157 const int collection_id; 158 const int profiler_id;
158 159
159 const PlatformThreadId target; // ID of The thread being sampled. 160 const PlatformThreadId target; // ID of The thread being sampled.
160 const SamplingParams params; // Information about how to sample. 161 const SamplingParams params; // Information about how to sample.
161 const CompletedCallback callback; // Callback made when sampling complete. 162 const CompletedCallback callback; // Callback made when sampling complete.
162 WaitableEvent* const finished; // Signaled when all sampling complete. 163 WaitableEvent* const finished; // Signaled when all sampling complete.
163 164
164 // Platform-specific module that does the actual sampling. 165 // Platform-specific module that does the actual sampling.
165 std::unique_ptr<NativeStackSampler> native_sampler; 166 std::unique_ptr<NativeStackSampler> native_sampler;
166 167
167 // The absolute time for the next sample. 168 // The absolute time for the next sample.
168 Time next_sample_time; 169 Time next_sample_time;
169 170
170 // The time that a profile was started, for calculating the total duration. 171 // The time that a profile was started, for calculating the total duration.
171 Time profile_start_time; 172 Time profile_start_time;
172 173
173 // Counters that indicate the current position along the acquisition. 174 // Counters that indicate the current position along the acquisition.
174 int burst = 0; 175 int burst = 0;
175 int sample = 0; 176 int sample = 0;
176 177
177 // The collected stack samples. The active profile is always at the back(). 178 // The collected stack samples. The active profile is always at the back().
178 CallStackProfiles profiles; 179 CallStackProfiles profiles;
179 180
180 private: 181 // Sequence number for generating new profiler ids.
181 static StaticAtomicSequenceNumber next_collection_id_; 182 static StaticAtomicSequenceNumber next_profiler_id;
182 }; 183 };
183 184
184 // Gets the single instance of this class. 185 // Gets the single instance of this class.
185 static SamplingThread* GetInstance(); 186 static SamplingThread* GetInstance();
186 187
187 // Adds a new CollectionContext to the thread. This can be called externally 188 // Adds a new CollectionContext to the thread. This can be called externally
188 // from any thread. This returns an ID that can later be used to stop 189 // from any thread. This returns an ID that can later be used to stop
189 // the sampling. 190 // the sampling.
190 int Add(std::unique_ptr<CollectionContext> collection); 191 int Add(std::unique_ptr<CollectionContext> collection);
191 192
(...skipping 29 matching lines...) Expand all
221 ~SamplingThread() override; 222 ~SamplingThread() override;
222 223
223 // Get task runner that is usable from the outside. 224 // Get task runner that is usable from the outside.
224 scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd(); 225 scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd();
225 scoped_refptr<SingleThreadTaskRunner> GetTaskRunner( 226 scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(
226 ThreadExecutionState* out_state); 227 ThreadExecutionState* out_state);
227 228
228 // Get task runner that is usable from the sampling thread itself. 229 // Get task runner that is usable from the sampling thread itself.
229 scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread(); 230 scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();
230 231
231 // Finishes a collection and reports collected data via callback. 232 // Finishes a collection and reports collected data via callback. Returns
232 void FinishCollection(CollectionContext* collection); 233 // the new collection params, if a new collection should be started. The
234 // |collection| should already have been removed from |active_collections_|
235 // by the caller, as this is needed to avoid flakyness in unit tests.
236 Optional<SamplingParams> FinishCollection(CollectionContext* collection);
233 237
234 // Records a single sample of a collection. 238 // Records a single sample of a collection.
235 void RecordSample(CollectionContext* collection); 239 void RecordSample(CollectionContext* collection);
236 240
237 // Check if the sampling thread is idle and begin a shutdown if it is. 241 // Check if the sampling thread is idle and begin a shutdown if it is.
238 void ScheduleShutdownIfIdle(); 242 void ScheduleShutdownIfIdle();
239 243
240 // These methods are tasks that get posted to the internal message queue. 244 // These methods are tasks that get posted to the internal message queue.
241 void AddCollectionTask(std::unique_ptr<CollectionContext> collection); 245 void AddCollectionTask(std::unique_ptr<CollectionContext> collection);
242 void RemoveCollectionTask(int id); 246 void RemoveCollectionTask(int id);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 358
355 // static 359 // static
356 void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownTaskAndSignalEvent( 360 void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownTaskAndSignalEvent(
357 SamplingThread* sampler, 361 SamplingThread* sampler,
358 int add_events, 362 int add_events,
359 WaitableEvent* event) { 363 WaitableEvent* event) {
360 sampler->ShutdownTask(add_events); 364 sampler->ShutdownTask(add_events);
361 event->Signal(); 365 event->Signal();
362 } 366 }
363 367
364 StaticAtomicSequenceNumber StackSamplingProfiler::SamplingThread:: 368 StaticAtomicSequenceNumber
365 CollectionContext::next_collection_id_; 369 StackSamplingProfiler::SamplingThread::CollectionContext::next_profiler_id;
366 370
367 StackSamplingProfiler::SamplingThread::SamplingThread() 371 StackSamplingProfiler::SamplingThread::SamplingThread()
368 : Thread("StackSamplingProfiler") {} 372 : Thread("StackSamplingProfiler") {}
369 373
370 StackSamplingProfiler::SamplingThread::~SamplingThread() = default; 374 StackSamplingProfiler::SamplingThread::~SamplingThread() = default;
371 375
372 StackSamplingProfiler::SamplingThread* 376 StackSamplingProfiler::SamplingThread*
373 StackSamplingProfiler::SamplingThread::GetInstance() { 377 StackSamplingProfiler::SamplingThread::GetInstance() {
374 return Singleton<SamplingThread, LeakySingletonTraits<SamplingThread>>::get(); 378 return Singleton<SamplingThread, LeakySingletonTraits<SamplingThread>>::get();
375 } 379 }
376 380
377 int StackSamplingProfiler::SamplingThread::Add( 381 int StackSamplingProfiler::SamplingThread::Add(
378 std::unique_ptr<CollectionContext> collection) { 382 std::unique_ptr<CollectionContext> collection) {
379 // This is not to be run on the sampling thread. 383 // This is not to be run on the sampling thread.
380 384
381 int id = collection->collection_id; 385 int id = collection->profiler_id;
382 scoped_refptr<SingleThreadTaskRunner> task_runner = 386 scoped_refptr<SingleThreadTaskRunner> task_runner =
383 GetOrCreateTaskRunnerForAdd(); 387 GetOrCreateTaskRunnerForAdd();
384 388
385 task_runner->PostTask( 389 task_runner->PostTask(
386 FROM_HERE, BindOnce(&SamplingThread::AddCollectionTask, Unretained(this), 390 FROM_HERE, BindOnce(&SamplingThread::AddCollectionTask, Unretained(this),
387 Passed(&collection))); 391 Passed(&collection)));
388 392
389 return id; 393 return id;
390 } 394 }
391 395
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 472
469 scoped_refptr<SingleThreadTaskRunner> 473 scoped_refptr<SingleThreadTaskRunner>
470 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() { 474 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
471 // This should be called only from the sampling thread as it has limited 475 // This should be called only from the sampling thread as it has limited
472 // accessibility. 476 // accessibility.
473 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 477 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
474 478
475 return Thread::task_runner(); 479 return Thread::task_runner();
476 } 480 }
477 481
478 void StackSamplingProfiler::SamplingThread::FinishCollection( 482 Optional<StackSamplingProfiler::SamplingParams>
483 StackSamplingProfiler::SamplingThread::FinishCollection(
479 CollectionContext* collection) { 484 CollectionContext* collection) {
480 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 485 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
486 DCHECK_EQ(0u, active_collections_.count(collection->profiler_id));
487 LOG(ERROR) << "FinishCollection call";
481 488
482 // If there is no duration for the final profile (because it was stopped), 489 // If there is no duration for the final profile (because it was stopped),
483 // calculate it now. 490 // calculate it now.
484 if (!collection->profiles.empty() && 491 if (!collection->profiles.empty() &&
485 collection->profiles.back().profile_duration == TimeDelta()) { 492 collection->profiles.back().profile_duration == TimeDelta()) {
486 collection->profiles.back().profile_duration = 493 collection->profiles.back().profile_duration =
487 Time::Now() - collection->profile_start_time; 494 Time::Now() - collection->profile_start_time +
495 collection->params.sampling_interval;
488 } 496 }
489 497
490 // Extract some information so callback and event-signalling can still be 498 // Extract some information so callback and event-signalling can still be
491 // done after the collection has been removed from the list of "active" ones. 499 // done after the collection has been removed from the list of "active" ones.
492 // This allows the the controlling object (and tests using it) to be confident 500 // This allows the the controlling object (and tests using it) to be confident
493 // that collection is fully finished when those things occur. 501 // that collection is fully finished when those things occur.
494 const CompletedCallback callback = collection->callback; 502 const CompletedCallback callback = collection->callback;
495 CallStackProfiles profiles = std::move(collection->profiles); 503 CallStackProfiles profiles = std::move(collection->profiles);
496 WaitableEvent* finished = collection->finished; 504 WaitableEvent* finished = collection->finished;
497 505
498 // Remove this collection from the map of known ones. The |collection|
499 // parameter is invalid after this point.
500 size_t count = active_collections_.erase(collection->collection_id);
501 DCHECK_EQ(1U, count);
502
503 // Run the associated callback, passing the collected profiles. 506 // Run the associated callback, passing the collected profiles.
504 callback.Run(std::move(profiles)); 507 Optional<SamplingParams> new_params = callback.Run(std::move(profiles));
508 LOG(ERROR) << "FinishCollection before signal, with new_params="
509 << new_params.has_value();
505 510
506 // Signal that this collection is finished. 511 // Signal that this collection is finished.
507 finished->Signal(); 512 finished->Signal();
513
514 return new_params;
508 } 515 }
509 516
510 void StackSamplingProfiler::SamplingThread::RecordSample( 517 void StackSamplingProfiler::SamplingThread::RecordSample(
511 CollectionContext* collection) { 518 CollectionContext* collection) {
512 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 519 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
513 DCHECK(collection->native_sampler); 520 DCHECK(collection->native_sampler);
514 521
515 // If this is the first sample of a burst, a new Profile needs to be created 522 // If this is the first sample of a burst, a new Profile needs to be created
516 // and filled. 523 // and filled.
517 if (collection->sample == 0) { 524 if (collection->sample == 0) {
518 collection->profiles.push_back(CallStackProfile()); 525 collection->profiles.push_back(CallStackProfile());
519 CallStackProfile& profile = collection->profiles.back(); 526 CallStackProfile& profile = collection->profiles.back();
520 profile.sampling_period = collection->params.sampling_interval; 527 profile.sampling_period = collection->params.sampling_interval;
521 collection->profile_start_time = Time::Now(); 528 collection->profile_start_time = Time::Now();
522 collection->native_sampler->ProfileRecordingStarting(&profile.modules); 529 collection->native_sampler->ProfileRecordingStarting(&profile.modules);
523 } 530 }
524 531
525 // The currently active profile being captured. 532 // The currently active profile being captured.
526 CallStackProfile& profile = collection->profiles.back(); 533 CallStackProfile& profile = collection->profiles.back();
527 534
528 // Record a single sample. 535 // Record a single sample.
529 profile.samples.push_back(Sample()); 536 profile.samples.push_back(Sample());
530 collection->native_sampler->RecordStackSample(stack_buffer_.get(), 537 collection->native_sampler->RecordStackSample(stack_buffer_.get(),
531 &profile.samples.back()); 538 &profile.samples.back());
532 539
533 // If this is the last sample of a burst, record the total time. 540 // If this is the last sample of a burst, record the total time.
534 if (collection->sample == collection->params.samples_per_burst - 1) { 541 if (collection->sample == collection->params.samples_per_burst - 1) {
535 profile.profile_duration = Time::Now() - collection->profile_start_time; 542 profile.profile_duration = Time::Now() - collection->profile_start_time +
543 collection->params.sampling_interval;
536 collection->native_sampler->ProfileRecordingStopped(stack_buffer_.get()); 544 collection->native_sampler->ProfileRecordingStopped(stack_buffer_.get());
537 } 545 }
538 } 546 }
539 547
540 void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() { 548 void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() {
541 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 549 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
542 550
543 if (!active_collections_.empty()) 551 if (!active_collections_.empty())
544 return; 552 return;
545 553
546 int add_events; 554 int add_events;
547 { 555 {
548 AutoLock lock(thread_execution_state_lock_); 556 AutoLock lock(thread_execution_state_lock_);
549 if (thread_execution_state_disable_idle_shutdown_for_testing_) 557 if (thread_execution_state_disable_idle_shutdown_for_testing_)
550 return; 558 return;
551 add_events = thread_execution_state_add_events_; 559 add_events = thread_execution_state_add_events_;
552 } 560 }
553 561
554 GetTaskRunnerOnSamplingThread()->PostDelayedTask( 562 GetTaskRunnerOnSamplingThread()->PostDelayedTask(
555 FROM_HERE, 563 FROM_HERE,
556 BindOnce(&SamplingThread::ShutdownTask, Unretained(this), add_events), 564 BindOnce(&SamplingThread::ShutdownTask, Unretained(this), add_events),
557 TimeDelta::FromSeconds(60)); 565 TimeDelta::FromSeconds(60));
558 } 566 }
559 567
560 void StackSamplingProfiler::SamplingThread::AddCollectionTask( 568 void StackSamplingProfiler::SamplingThread::AddCollectionTask(
561 std::unique_ptr<CollectionContext> collection) { 569 std::unique_ptr<CollectionContext> collection) {
562 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 570 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
563 571
564 const int collection_id = collection->collection_id; 572 const int profiler_id = collection->profiler_id;
565 const TimeDelta initial_delay = collection->params.initial_delay; 573 const TimeDelta initial_delay = collection->params.initial_delay;
566 574
567 active_collections_.insert( 575 active_collections_.insert(
568 std::make_pair(collection_id, std::move(collection))); 576 std::make_pair(profiler_id, std::move(collection)));
569 577
570 GetTaskRunnerOnSamplingThread()->PostDelayedTask( 578 GetTaskRunnerOnSamplingThread()->PostDelayedTask(
571 FROM_HERE, 579 FROM_HERE,
572 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), 580 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this),
573 collection_id), 581 profiler_id),
574 initial_delay); 582 initial_delay);
575 583
576 // Another increment of "add events" serves to invalidate any pending 584 // Another increment of "add events" serves to invalidate any pending
577 // shutdown tasks that may have been initiated between the Add() and this 585 // shutdown tasks that may have been initiated between the Add() and this
578 // task running. 586 // task running.
579 { 587 {
580 AutoLock lock(thread_execution_state_lock_); 588 AutoLock lock(thread_execution_state_lock_);
581 ++thread_execution_state_add_events_; 589 ++thread_execution_state_add_events_;
582 } 590 }
583 } 591 }
584 592
585 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) { 593 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) {
586 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 594 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
587 595
588 auto found = active_collections_.find(id); 596 auto found = active_collections_.find(id);
589 if (found == active_collections_.end()) 597 if (found == active_collections_.end())
590 return; 598 return;
591 599
592 FinishCollection(found->second.get()); 600 // Remove |collection| from |active_collections_|.
601 std::unique_ptr<CollectionContext> collection = std::move(found->second);
602 size_t count = active_collections_.erase(id);
603 DCHECK_EQ(1U, count);
604
605 FinishCollection(collection.get());
593 ScheduleShutdownIfIdle(); 606 ScheduleShutdownIfIdle();
594 } 607 }
595 608
596 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) { 609 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) {
597 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 610 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
598 611
599 auto found = active_collections_.find(id); 612 auto found = active_collections_.find(id);
600 613
601 // The task won't be found if it has been stopped. 614 // The task won't be found if it has been stopped.
602 if (found == active_collections_.end()) 615 if (found == active_collections_.end())
603 return; 616 return;
604 617
605 CollectionContext* collection = found->second.get(); 618 CollectionContext* collection = found->second.get();
606 619
607 // Handle first-run with no "next time". 620 // Handle first-run with no "next time".
608 if (collection->next_sample_time == Time()) 621 if (collection->next_sample_time == Time())
609 collection->next_sample_time = Time::Now(); 622 collection->next_sample_time = Time::Now();
610 623
611 // Do the collection of a single sample. 624 // Do the collection of a single sample.
612 RecordSample(collection); 625 RecordSample(collection);
613 626
614 // Update the time of the next sample recording. 627 // Update the time of the next sample recording.
615 if (UpdateNextSampleTime(collection)) { 628 const bool collection_finished = !UpdateNextSampleTime(collection);
629 if (!collection_finished) {
616 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask( 630 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
617 FROM_HERE, 631 FROM_HERE,
618 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), id), 632 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), id),
619 std::max(collection->next_sample_time - Time::Now(), TimeDelta())); 633 std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
620 DCHECK(success); 634 DCHECK(success);
621 } else { 635 return;
622 // All capturing has completed so finish the collection. By not re-adding 636 }
623 // it to the task queue, the collection will "expire" (i.e. no further work 637 LOG(ERROR) << "Collection finished";
624 // will be done). The |collection| variable will be invalid after this call. 638
625 FinishCollection(collection); 639 // Take ownership of |collection| and remove it from the map. If collection is
640 // to be restarted, a new collection task will be added below.
641 std::unique_ptr<CollectionContext> owned_collection =
642 std::move(found->second);
643 size_t count = active_collections_.erase(id);
644 DCHECK_EQ(1U, count);
645
646 // All capturing has completed so finish the collection. If no new params
647 // are returned, a new collection should not be started.
648 Optional<SamplingParams> new_params = FinishCollection(collection);
649 if (!new_params.has_value()) {
650 // By not adding it to the task queue, the collection will "expire" (i.e.
651 // no further work will be done).
626 ScheduleShutdownIfIdle(); 652 ScheduleShutdownIfIdle();
653 return;
627 } 654 }
655 LOG(ERROR) << "Scheduling new collection";
656
657 // Restart the collection with the new params. Keep the same id so the
658 // Stop() operation continues to work.
659 auto new_collection = MakeUnique<SamplingThread::CollectionContext>(
660 id, collection->target, new_params.value(), collection->callback,
661 collection->finished, std::move(collection->native_sampler));
662 AddCollectionTask(std::move(new_collection));
628 } 663 }
629 664
630 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) { 665 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
631 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 666 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
632 667
633 // Holding this lock ensures that any attempt to start another job will 668 // Holding this lock ensures that any attempt to start another job will
634 // get postponed until |thread_execution_state_| is updated, thus eliminating 669 // get postponed until |thread_execution_state_| is updated, thus eliminating
635 // the race in starting a new thread while the previous one is exiting. 670 // the race in starting a new thread while the previous one is exiting.
636 AutoLock lock(thread_execution_state_lock_); 671 AutoLock lock(thread_execution_state_lock_);
637 672
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 const SamplingParams& params, 772 const SamplingParams& params,
738 const CompletedCallback& callback, 773 const CompletedCallback& callback,
739 NativeStackSamplerTestDelegate* test_delegate) 774 NativeStackSamplerTestDelegate* test_delegate)
740 : thread_id_(thread_id), 775 : thread_id_(thread_id),
741 params_(params), 776 params_(params),
742 completed_callback_(callback), 777 completed_callback_(callback),
743 // The event starts "signaled" so code knows it's safe to start thread 778 // The event starts "signaled" so code knows it's safe to start thread
744 // and "manual" so that it can be waited in multiple places. 779 // and "manual" so that it can be waited in multiple places.
745 profiling_inactive_(WaitableEvent::ResetPolicy::MANUAL, 780 profiling_inactive_(WaitableEvent::ResetPolicy::MANUAL,
746 WaitableEvent::InitialState::SIGNALED), 781 WaitableEvent::InitialState::SIGNALED),
747 collection_id_(NULL_COLLECTION_ID), 782 profiler_id_(NULL_PROFILER_ID),
748 test_delegate_(test_delegate) {} 783 test_delegate_(test_delegate) {}
749 784
750 StackSamplingProfiler::~StackSamplingProfiler() { 785 StackSamplingProfiler::~StackSamplingProfiler() {
751 // Stop returns immediately but the shutdown runs asynchronously. There is a 786 // Stop returns immediately but the shutdown runs asynchronously. There is a
752 // non-zero probability that one more sample will be taken after this call 787 // non-zero probability that one more sample will be taken after this call
753 // returns. 788 // returns.
754 Stop(); 789 Stop();
755 790
756 // The behavior of sampling a thread that has exited is undefined and could 791 // The behavior of sampling a thread that has exited is undefined and could
757 // cause Bad Things(tm) to occur. The safety model provided by this class is 792 // cause Bad Things(tm) to occur. The safety model provided by this class is
(...skipping 16 matching lines...) Expand all
774 NativeStackSampler::Create(thread_id_, &RecordAnnotations, 809 NativeStackSampler::Create(thread_id_, &RecordAnnotations,
775 test_delegate_); 810 test_delegate_);
776 811
777 if (!native_sampler) 812 if (!native_sampler)
778 return; 813 return;
779 814
780 // Wait for profiling to be "inactive", then reset it for the upcoming run. 815 // Wait for profiling to be "inactive", then reset it for the upcoming run.
781 profiling_inactive_.Wait(); 816 profiling_inactive_.Wait();
782 profiling_inactive_.Reset(); 817 profiling_inactive_.Reset();
783 818
784 DCHECK_EQ(NULL_COLLECTION_ID, collection_id_); 819 DCHECK_EQ(NULL_PROFILER_ID, profiler_id_);
785 collection_id_ = SamplingThread::GetInstance()->Add( 820 profiler_id_ = SamplingThread::GetInstance()->Add(
786 MakeUnique<SamplingThread::CollectionContext>( 821 MakeUnique<SamplingThread::CollectionContext>(
822 SamplingThread::CollectionContext::next_profiler_id.GetNext(),
787 thread_id_, params_, completed_callback_, &profiling_inactive_, 823 thread_id_, params_, completed_callback_, &profiling_inactive_,
788 std::move(native_sampler))); 824 std::move(native_sampler)));
789 DCHECK_NE(NULL_COLLECTION_ID, collection_id_); 825 DCHECK_NE(NULL_PROFILER_ID, profiler_id_);
790 } 826 }
791 827
792 void StackSamplingProfiler::Stop() { 828 void StackSamplingProfiler::Stop() {
793 SamplingThread::GetInstance()->Remove(collection_id_); 829 SamplingThread::GetInstance()->Remove(profiler_id_);
794 collection_id_ = NULL_COLLECTION_ID; 830 profiler_id_ = NULL_PROFILER_ID;
795 } 831 }
796 832
797 // static 833 // static
798 void StackSamplingProfiler::SetProcessMilestone(int milestone) { 834 void StackSamplingProfiler::SetProcessMilestone(int milestone) {
799 DCHECK_LE(0, milestone); 835 DCHECK_LE(0, milestone);
800 DCHECK_GT(static_cast<int>(sizeof(process_milestones_) * 8), milestone); 836 DCHECK_GT(static_cast<int>(sizeof(process_milestones_) * 8), milestone);
801 DCHECK_EQ(0, subtle::NoBarrier_Load(&process_milestones_) & (1 << milestone)); 837 DCHECK_EQ(0, subtle::NoBarrier_Load(&process_milestones_) & (1 << milestone));
802 ChangeAtomicFlags(&process_milestones_, 1 << milestone, 0); 838 ChangeAtomicFlags(&process_milestones_, 1 << milestone, 0);
803 } 839 }
804 840
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 881 }
846 882
847 bool operator<(const StackSamplingProfiler::Frame &a, 883 bool operator<(const StackSamplingProfiler::Frame &a,
848 const StackSamplingProfiler::Frame &b) { 884 const StackSamplingProfiler::Frame &b) {
849 return (a.module_index < b.module_index) || 885 return (a.module_index < b.module_index) ||
850 (a.module_index == b.module_index && 886 (a.module_index == b.module_index &&
851 a.instruction_pointer < b.instruction_pointer); 887 a.instruction_pointer < b.instruction_pointer);
852 } 888 }
853 889
854 } // namespace base 890 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698