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

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

Issue 2927593002: Make stack sampling profiler sample beyond startup. (Closed)
Patch Set: Address some comments. 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 callback(callback), 150 callback(callback),
151 finished(finished), 151 finished(finished),
152 native_sampler(std::move(sampler)) {} 152 native_sampler(std::move(sampler)) {}
153 ~CollectionContext() {} 153 ~CollectionContext() {}
154 154
155 // An identifier for this collection, used to uniquely identify it to 155 // An identifier for this collection, used to uniquely identify it to
156 // outside interests. 156 // outside interests.
157 const int collection_id; 157 const int collection_id;
158 158
159 const PlatformThreadId target; // ID of The thread being sampled. 159 const PlatformThreadId target; // ID of The thread being sampled.
160 const SamplingParams params; // Information about how to sample. 160
161 // Information about how to sample. Not const because they can be updated
162 // upon collection completion by |callback|.
163 SamplingParams params;
164
161 const CompletedCallback callback; // Callback made when sampling complete. 165 const CompletedCallback callback; // Callback made when sampling complete.
162 WaitableEvent* const finished; // Signaled when all sampling complete. 166 WaitableEvent* const finished; // Signaled when all sampling complete.
163 167
164 // Platform-specific module that does the actual sampling. 168 // Platform-specific module that does the actual sampling.
165 std::unique_ptr<NativeStackSampler> native_sampler; 169 std::unique_ptr<NativeStackSampler> native_sampler;
166 170
167 // The absolute time for the next sample. 171 // The absolute time for the next sample.
168 Time next_sample_time; 172 Time next_sample_time;
169 173
170 // The time that a profile was started, for calculating the total duration. 174 // The time that a profile was started, for calculating the total duration.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 ~SamplingThread() override; 225 ~SamplingThread() override;
222 226
223 // Get task runner that is usable from the outside. 227 // Get task runner that is usable from the outside.
224 scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd(); 228 scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd();
225 scoped_refptr<SingleThreadTaskRunner> GetTaskRunner( 229 scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(
226 ThreadExecutionState* out_state); 230 ThreadExecutionState* out_state);
227 231
228 // Get task runner that is usable from the sampling thread itself. 232 // Get task runner that is usable from the sampling thread itself.
229 scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread(); 233 scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();
230 234
231 // Finishes a collection and reports collected data via callback. 235 // Finishes a collection and reports collected data via callback. Returns
232 void FinishCollection(CollectionContext* collection); 236 // whether collection should be restarted per the callback.
237 bool FinishCollection(CollectionContext* collection);
233 238
234 // Records a single sample of a collection. 239 // Records a single sample of a collection.
235 void RecordSample(CollectionContext* collection); 240 void RecordSample(CollectionContext* collection);
236 241
237 // Check if the sampling thread is idle and begin a shutdown if it is. 242 // Check if the sampling thread is idle and begin a shutdown if it is.
238 void ScheduleShutdownIfIdle(); 243 void ScheduleShutdownIfIdle();
239 244
240 // These methods are tasks that get posted to the internal message queue. 245 // These methods are tasks that get posted to the internal message queue.
241 void AddCollectionTask(std::unique_ptr<CollectionContext> collection); 246 void AddCollectionTask(std::unique_ptr<CollectionContext> collection);
242 void RemoveCollectionTask(int id); 247 void RemoveCollectionTask(int id);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 473
469 scoped_refptr<SingleThreadTaskRunner> 474 scoped_refptr<SingleThreadTaskRunner>
470 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() { 475 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
471 // This should be called only from the sampling thread as it has limited 476 // This should be called only from the sampling thread as it has limited
472 // accessibility. 477 // accessibility.
473 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 478 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
474 479
475 return Thread::task_runner(); 480 return Thread::task_runner();
476 } 481 }
477 482
478 void StackSamplingProfiler::SamplingThread::FinishCollection( 483 bool StackSamplingProfiler::SamplingThread::FinishCollection(
479 CollectionContext* collection) { 484 CollectionContext* collection) {
480 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 485 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
481 486
482 // If there is no duration for the final profile (because it was stopped), 487 // If there is no duration for the final profile (because it was stopped),
483 // calculate it now. 488 // calculate it now.
484 if (!collection->profiles.empty() && 489 if (!collection->profiles.empty() &&
485 collection->profiles.back().profile_duration == TimeDelta()) { 490 collection->profiles.back().profile_duration == TimeDelta()) {
486 collection->profiles.back().profile_duration = 491 collection->profiles.back().profile_duration =
487 Time::Now() - collection->profile_start_time; 492 Time::Now() - collection->profile_start_time;
488 } 493 }
489 494
490 // Extract some information so callback and event-signalling can still be 495 // 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. 496 // 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 497 // This allows the the controlling object (and tests using it) to be confident
493 // that collection is fully finished when those things occur. 498 // that collection is fully finished when those things occur.
494 const CompletedCallback callback = collection->callback; 499 const CompletedCallback callback = collection->callback;
495 CallStackProfiles profiles = std::move(collection->profiles); 500 CallStackProfiles profiles = std::move(collection->profiles);
496 WaitableEvent* finished = collection->finished; 501 WaitableEvent* finished = collection->finished;
497 502
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. 503 // Run the associated callback, passing the collected profiles.
504 callback.Run(std::move(profiles)); 504 bool restart_collection =
505 callback.Run(std::move(profiles), &collection->params);
505 506
506 // Signal that this collection is finished. 507 // Signal that this collection is finished.
507 finished->Signal(); 508 finished->Signal();
509
510 return restart_collection;
508 } 511 }
509 512
510 void StackSamplingProfiler::SamplingThread::RecordSample( 513 void StackSamplingProfiler::SamplingThread::RecordSample(
511 CollectionContext* collection) { 514 CollectionContext* collection) {
512 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 515 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
513 DCHECK(collection->native_sampler); 516 DCHECK(collection->native_sampler);
514 517
515 // If this is the first sample of a burst, a new Profile needs to be created 518 // If this is the first sample of a burst, a new Profile needs to be created
516 // and filled. 519 // and filled.
517 if (collection->sample == 0) { 520 if (collection->sample == 0) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 } 585 }
583 } 586 }
584 587
585 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) { 588 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) {
586 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 589 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
587 590
588 auto found = active_collections_.find(id); 591 auto found = active_collections_.find(id);
589 if (found == active_collections_.end()) 592 if (found == active_collections_.end())
590 return; 593 return;
591 594
592 FinishCollection(found->second.get()); 595 auto* collection = found->second.get();
596 FinishCollection(collection);
597
598 // Remove this collection from the map of known ones. The |collection|
599 // parameter is invalid after this point.
600 size_t count = active_collections_.erase(collection->collection_id);
601 DCHECK_EQ(1U, count);
602
593 ScheduleShutdownIfIdle(); 603 ScheduleShutdownIfIdle();
594 } 604 }
595 605
596 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) { 606 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) {
597 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 607 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
598 608
599 auto found = active_collections_.find(id); 609 auto found = active_collections_.find(id);
600 610
601 // The task won't be found if it has been stopped. 611 // The task won't be found if it has been stopped.
602 if (found == active_collections_.end()) 612 if (found == active_collections_.end())
603 return; 613 return;
604 614
605 CollectionContext* collection = found->second.get(); 615 CollectionContext* collection = found->second.get();
606 616
607 // Handle first-run with no "next time". 617 // Handle first-run with no "next time".
608 if (collection->next_sample_time == Time()) 618 if (collection->next_sample_time == Time())
609 collection->next_sample_time = Time::Now(); 619 collection->next_sample_time = Time::Now();
610 620
611 // Do the collection of a single sample. 621 // Do the collection of a single sample.
612 RecordSample(collection); 622 RecordSample(collection);
613 623
614 // Update the time of the next sample recording. 624 // Update the time of the next sample recording.
615 if (UpdateNextSampleTime(collection)) { 625 bool collection_finished = !UpdateNextSampleTime(collection);
616 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask( 626 if (collection_finished) {
617 FROM_HERE, 627 // All capturing has completed so finish the collection.
618 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), id), 628 collection_finished = !FinishCollection(collection);
619 std::max(collection->next_sample_time - Time::Now(), TimeDelta())); 629 if (!collection_finished) {
620 DCHECK(success); 630 // Attempt to restart the collection with the new params.
621 } else { 631 collection->next_sample_time =
Mike Wittman 2017/07/01 02:44:06 I'd prefer to create a new CollectionContext and s
Alexei Svitkine (slow) 2017/07/06 15:51:09 Done.
622 // All capturing has completed so finish the collection. By not re-adding 632 Time::Now() + collection->params.initial_delay;
623 // it to the task queue, the collection will "expire" (i.e. no further work 633 collection->burst = 0;
624 // will be done). The |collection| variable will be invalid after this call. 634 collection->sample = 0;
625 FinishCollection(collection); 635 }
636 }
637
638 if (collection_finished) {
639 // Remove this collection from the map of known ones. The |collection|
640 // parameter is invalid after this point.
641 size_t count = active_collections_.erase(collection->collection_id);
642 DCHECK_EQ(1U, count);
643
644 // By not adding it to the task queue, the collection will "expire" (i.e.
645 // no further work will be done). The |collection| variable will be invalid
646 // after this call.
626 ScheduleShutdownIfIdle(); 647 ScheduleShutdownIfIdle();
648 return;
627 } 649 }
650
651 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
652 FROM_HERE,
653 BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), id),
654 std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
655 DCHECK(success);
628 } 656 }
629 657
630 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) { 658 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
631 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 659 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
632 660
633 // Holding this lock ensures that any attempt to start another job will 661 // Holding this lock ensures that any attempt to start another job will
634 // get postponed until |thread_execution_state_| is updated, thus eliminating 662 // get postponed until |thread_execution_state_| is updated, thus eliminating
635 // the race in starting a new thread while the previous one is exiting. 663 // the race in starting a new thread while the previous one is exiting.
636 AutoLock lock(thread_execution_state_lock_); 664 AutoLock lock(thread_execution_state_lock_);
637 665
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 873 }
846 874
847 bool operator<(const StackSamplingProfiler::Frame &a, 875 bool operator<(const StackSamplingProfiler::Frame &a,
848 const StackSamplingProfiler::Frame &b) { 876 const StackSamplingProfiler::Frame &b) {
849 return (a.module_index < b.module_index) || 877 return (a.module_index < b.module_index) ||
850 (a.module_index == b.module_index && 878 (a.module_index == b.module_index &&
851 a.instruction_pointer < b.instruction_pointer); 879 a.instruction_pointer < b.instruction_pointer);
852 } 880 }
853 881
854 } // namespace base 882 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698