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

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

Issue 2927593002: Make stack sampling profiler sample beyond startup. (Closed)
Patch Set: Created 3 years, 6 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 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 471
467 scoped_refptr<SingleThreadTaskRunner> 472 scoped_refptr<SingleThreadTaskRunner>
468 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() { 473 StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
469 // This should be called only from the sampling thread as it has limited 474 // This should be called only from the sampling thread as it has limited
470 // accessibility. 475 // accessibility.
471 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 476 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
472 477
473 return Thread::task_runner(); 478 return Thread::task_runner();
474 } 479 }
475 480
476 void StackSamplingProfiler::SamplingThread::FinishCollection( 481 bool StackSamplingProfiler::SamplingThread::FinishCollection(
477 CollectionContext* collection) { 482 CollectionContext* collection) {
478 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 483 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
479 484
480 // If there is no duration for the final profile (because it was stopped), 485 // If there is no duration for the final profile (because it was stopped),
481 // calculate it now. 486 // calculate it now.
482 if (!collection->profiles.empty() && 487 if (!collection->profiles.empty() &&
483 collection->profiles.back().profile_duration == TimeDelta()) { 488 collection->profiles.back().profile_duration == TimeDelta()) {
484 collection->profiles.back().profile_duration = 489 collection->profiles.back().profile_duration =
485 Time::Now() - collection->profile_start_time; 490 Time::Now() - collection->profile_start_time;
486 } 491 }
487 492
488 // Extract some information so callback and event-signalling can still be 493 // Extract some information so callback and event-signalling can still be
489 // done after the collection has been removed from the list of "active" ones. 494 // done after the collection has been removed from the list of "active" ones.
490 // This allows the the controlling object (and tests using it) to be confident 495 // This allows the the controlling object (and tests using it) to be confident
491 // that collection is fully finished when those things occur. 496 // that collection is fully finished when those things occur.
492 const CompletedCallback callback = collection->callback; 497 const CompletedCallback callback = collection->callback;
493 CallStackProfiles profiles = std::move(collection->profiles); 498 CallStackProfiles profiles = std::move(collection->profiles);
494 WaitableEvent* finished = collection->finished; 499 WaitableEvent* finished = collection->finished;
495 500
496 // Remove this collection from the map of known ones. The |collection|
497 // parameter is invalid after this point.
498 size_t count = active_collections_.erase(collection->collection_id);
499 DCHECK_EQ(1U, count);
500
501 // Run the associated callback, passing the collected profiles. 501 // Run the associated callback, passing the collected profiles.
502 callback.Run(std::move(profiles)); 502 bool restart_collection =
503 callback.Run(std::move(profiles), &collection->params);
503 504
504 // Signal that this collection is finished. 505 // Signal that this collection is finished.
505 finished->Signal(); 506 finished->Signal();
507
508 return restart_collection;
506 } 509 }
507 510
508 void StackSamplingProfiler::SamplingThread::RecordSample( 511 void StackSamplingProfiler::SamplingThread::RecordSample(
509 CollectionContext* collection) { 512 CollectionContext* collection) {
510 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 513 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
511 DCHECK(collection->native_sampler); 514 DCHECK(collection->native_sampler);
512 515
513 // If this is the first sample of a burst, a new Profile needs to be created 516 // If this is the first sample of a burst, a new Profile needs to be created
514 // and filled. 517 // and filled.
515 if (collection->sample == 0) { 518 if (collection->sample == 0) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 } 583 }
581 } 584 }
582 585
583 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) { 586 void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) {
584 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 587 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
585 588
586 auto found = active_collections_.find(id); 589 auto found = active_collections_.find(id);
587 if (found == active_collections_.end()) 590 if (found == active_collections_.end())
588 return; 591 return;
589 592
590 FinishCollection(found->second.get()); 593 auto* collection = found->second.get();
594 FinishCollection(collection);
595
596 // Remove this collection from the map of known ones. The |collection|
597 // parameter is invalid after this point.
598 size_t count = active_collections_.erase(collection->collection_id);
599 DCHECK_EQ(1U, count);
600
591 ScheduleShutdownIfIdle(); 601 ScheduleShutdownIfIdle();
592 } 602 }
593 603
594 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) { 604 void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) {
595 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 605 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
596 606
597 auto found = active_collections_.find(id); 607 auto found = active_collections_.find(id);
598 608
599 // The task won't be found if it has been stopped. 609 // The task won't be found if it has been stopped.
600 if (found == active_collections_.end()) 610 if (found == active_collections_.end())
601 return; 611 return;
602 612
603 CollectionContext* collection = found->second.get(); 613 CollectionContext* collection = found->second.get();
604 614
605 // Handle first-run with no "next time". 615 // Handle first-run with no "next time".
606 if (collection->next_sample_time == Time()) 616 if (collection->next_sample_time == Time())
607 collection->next_sample_time = Time::Now(); 617 collection->next_sample_time = Time::Now();
608 618
609 // Do the collection of a single sample. 619 // Do the collection of a single sample.
610 RecordSample(collection); 620 RecordSample(collection);
611 621
612 // Update the time of the next sample recording. 622 // Update the time of the next sample recording.
613 if (UpdateNextSampleTime(collection)) { 623 bool collection_finished = !UpdateNextSampleTime(collection);
614 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask( 624 if (collection_finished) {
615 FROM_HERE, 625 // All capturing has completed so finish the collection.
616 Bind(&SamplingThread::PerformCollectionTask, Unretained(this), id), 626 collection_finished = !FinishCollection(collection);
617 std::max(collection->next_sample_time - Time::Now(), TimeDelta())); 627 if (!collection_finished) {
618 DCHECK(success); 628 // Attempt to restart the collection with the new params.
619 } else { 629 collection->next_sample_time =
620 // All capturing has completed so finish the collection. By not re-adding 630 Time::Now() + collection->params.initial_delay;
621 // it to the task queue, the collection will "expire" (i.e. no further work 631 collection->burst = 0;
622 // will be done). The |collection| variable will be invalid after this call. 632 collection->sample = 0;
623 FinishCollection(collection); 633 }
634 }
635
636 if (collection_finished) {
637 // Remove this collection from the map of known ones. The |collection|
638 // parameter is invalid after this point.
639 size_t count = active_collections_.erase(collection->collection_id);
640 DCHECK_EQ(1U, count);
641
642 // By not adding it to the task queue, the collection will "expire" (i.e.
643 // no further work will be done). The |collection| variable will be invalid
644 // after this call.
624 ScheduleShutdownIfIdle(); 645 ScheduleShutdownIfIdle();
646 return;
625 } 647 }
648
649 bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
650 FROM_HERE,
651 Bind(&SamplingThread::PerformCollectionTask, Unretained(this), id),
652 std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
653 DCHECK(success);
626 } 654 }
627 655
628 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) { 656 void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
629 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); 657 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
630 658
631 // Holding this lock ensures that any attempt to start another job will 659 // Holding this lock ensures that any attempt to start another job will
632 // get postponed until |thread_execution_state_| is updated, thus eliminating 660 // get postponed until |thread_execution_state_| is updated, thus eliminating
633 // the race in starting a new thread while the previous one is exiting. 661 // the race in starting a new thread while the previous one is exiting.
634 AutoLock lock(thread_execution_state_lock_); 662 AutoLock lock(thread_execution_state_lock_);
635 663
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 } 871 }
844 872
845 bool operator<(const StackSamplingProfiler::Frame &a, 873 bool operator<(const StackSamplingProfiler::Frame &a,
846 const StackSamplingProfiler::Frame &b) { 874 const StackSamplingProfiler::Frame &b) {
847 return (a.module_index < b.module_index) || 875 return (a.module_index < b.module_index) ||
848 (a.module_index == b.module_index && 876 (a.module_index == b.module_index &&
849 a.instruction_pointer < b.instruction_pointer); 877 a.instruction_pointer < b.instruction_pointer);
850 } 878 }
851 879
852 } // namespace base 880 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698