| OLD | NEW |
| 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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 void PerformCollectionTask(int id); | 243 void PerformCollectionTask(int id); |
| 244 void ShutdownTask(int add_events); | 244 void ShutdownTask(int add_events); |
| 245 | 245 |
| 246 // Updates the |next_sample_time| time based on configured parameters. | 246 // Updates the |next_sample_time| time based on configured parameters. |
| 247 // Returns true if there is a next sample or false if sampling is complete. | 247 // Returns true if there is a next sample or false if sampling is complete. |
| 248 bool UpdateNextSampleTime(CollectionContext* collection); | 248 bool UpdateNextSampleTime(CollectionContext* collection); |
| 249 | 249 |
| 250 // Thread: | 250 // Thread: |
| 251 void CleanUp() override; | 251 void CleanUp() override; |
| 252 | 252 |
| 253 // A stack-buffer used by the native sampler for its work. This buffer can |
| 254 // be re-used for multiple native sampler objects so long as the API calls |
| 255 // that take it are not called concurrently. |
| 256 std::unique_ptr<NativeStackSampler::StackBuffer> stack_buffer_; |
| 257 |
| 253 // A map of IDs to collection contexts. Because this class is a singleton | 258 // A map of IDs to collection contexts. Because this class is a singleton |
| 254 // that is never destroyed, context objects will never be destructed except | 259 // that is never destroyed, context objects will never be destructed except |
| 255 // by explicit action. Thus, it's acceptable to pass unretained pointers | 260 // by explicit action. Thus, it's acceptable to pass unretained pointers |
| 256 // to these objects when posting tasks. | 261 // to these objects when posting tasks. |
| 257 std::map<int, std::unique_ptr<CollectionContext>> active_collections_; | 262 std::map<int, std::unique_ptr<CollectionContext>> active_collections_; |
| 258 | 263 |
| 259 // State maintained about the current execution (or non-execution) of | 264 // State maintained about the current execution (or non-execution) of |
| 260 // the thread. This state must always be accessed while holding the | 265 // the thread. This state must always be accessed while holding the |
| 261 // lock. A copy of the task-runner is maintained here for use by any | 266 // lock. A copy of the task-runner is maintained here for use by any |
| 262 // calling thread; this is necessary because Thread's accessor for it is | 267 // calling thread; this is necessary because Thread's accessor for it is |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 DCHECK_NE(GetThreadId(), PlatformThread::CurrentId()); | 419 DCHECK_NE(GetThreadId(), PlatformThread::CurrentId()); |
| 415 return thread_execution_state_task_runner_; | 420 return thread_execution_state_task_runner_; |
| 416 } | 421 } |
| 417 | 422 |
| 418 if (thread_execution_state_ == EXITING) { | 423 if (thread_execution_state_ == EXITING) { |
| 419 // The previous instance has only been partially cleaned up. It is necessary | 424 // The previous instance has only been partially cleaned up. It is necessary |
| 420 // to call Stop() before Start(). | 425 // to call Stop() before Start(). |
| 421 Stop(); | 426 Stop(); |
| 422 } | 427 } |
| 423 | 428 |
| 429 DCHECK(!stack_buffer_); |
| 430 stack_buffer_ = NativeStackSampler::CreateStackBuffer(); |
| 431 |
| 424 // The thread is not running. Start it and get associated runner. The task- | 432 // The thread is not running. Start it and get associated runner. The task- |
| 425 // runner has to be saved for future use because though it can be used from | 433 // runner has to be saved for future use because though it can be used from |
| 426 // any thread, it can be acquired via task_runner() only on the created | 434 // any thread, it can be acquired via task_runner() only on the created |
| 427 // thread and the thread that creates it (i.e. this thread) for thread-safety | 435 // thread and the thread that creates it (i.e. this thread) for thread-safety |
| 428 // reasons which are alleviated in SamplingThread by gating access to it with | 436 // reasons which are alleviated in SamplingThread by gating access to it with |
| 429 // the |thread_execution_state_lock_|. | 437 // the |thread_execution_state_lock_|. |
| 430 Start(); | 438 Start(); |
| 431 thread_execution_state_ = RUNNING; | 439 thread_execution_state_ = RUNNING; |
| 432 thread_execution_state_task_runner_ = Thread::task_runner(); | 440 thread_execution_state_task_runner_ = Thread::task_runner(); |
| 433 | 441 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 profile.sampling_period = collection->params.sampling_interval; | 518 profile.sampling_period = collection->params.sampling_interval; |
| 511 collection->profile_start_time = Time::Now(); | 519 collection->profile_start_time = Time::Now(); |
| 512 collection->native_sampler->ProfileRecordingStarting(&profile.modules); | 520 collection->native_sampler->ProfileRecordingStarting(&profile.modules); |
| 513 } | 521 } |
| 514 | 522 |
| 515 // The currently active profile being captured. | 523 // The currently active profile being captured. |
| 516 CallStackProfile& profile = collection->profiles.back(); | 524 CallStackProfile& profile = collection->profiles.back(); |
| 517 | 525 |
| 518 // Record a single sample. | 526 // Record a single sample. |
| 519 profile.samples.push_back(Sample()); | 527 profile.samples.push_back(Sample()); |
| 520 collection->native_sampler->RecordStackSample(&profile.samples.back()); | 528 collection->native_sampler->RecordStackSample(stack_buffer_.get(), |
| 529 &profile.samples.back()); |
| 521 | 530 |
| 522 // If this is the last sample of a burst, record the total time. | 531 // If this is the last sample of a burst, record the total time. |
| 523 if (collection->sample == collection->params.samples_per_burst - 1) { | 532 if (collection->sample == collection->params.samples_per_burst - 1) { |
| 524 profile.profile_duration = Time::Now() - collection->profile_start_time; | 533 profile.profile_duration = Time::Now() - collection->profile_start_time; |
| 525 collection->native_sampler->ProfileRecordingStopped(); | 534 collection->native_sampler->ProfileRecordingStopped(stack_buffer_.get()); |
| 526 } | 535 } |
| 527 } | 536 } |
| 528 | 537 |
| 529 void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() { | 538 void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() { |
| 530 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); | 539 DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); |
| 531 | 540 |
| 532 if (!active_collections_.empty()) | 541 if (!active_collections_.empty()) |
| 533 return; | 542 return; |
| 534 | 543 |
| 535 int add_events; | 544 int add_events; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 // (again) in order for Stop/Start to be called (again) should more work | 649 // (again) in order for Stop/Start to be called (again) should more work |
| 641 // come in. Holding the |thread_execution_state_lock_| ensures the necessary | 650 // come in. Holding the |thread_execution_state_lock_| ensures the necessary |
| 642 // happens-after with regard to this detach and future Thread API calls. | 651 // happens-after with regard to this detach and future Thread API calls. |
| 643 DetachFromSequence(); | 652 DetachFromSequence(); |
| 644 | 653 |
| 645 // Set the thread_state variable so the thread will be restarted when new | 654 // Set the thread_state variable so the thread will be restarted when new |
| 646 // work comes in. Remove the |thread_execution_state_task_runner_| to avoid | 655 // work comes in. Remove the |thread_execution_state_task_runner_| to avoid |
| 647 // confusion. | 656 // confusion. |
| 648 thread_execution_state_ = EXITING; | 657 thread_execution_state_ = EXITING; |
| 649 thread_execution_state_task_runner_ = nullptr; | 658 thread_execution_state_task_runner_ = nullptr; |
| 659 stack_buffer_.reset(); |
| 650 } | 660 } |
| 651 | 661 |
| 652 bool StackSamplingProfiler::SamplingThread::UpdateNextSampleTime( | 662 bool StackSamplingProfiler::SamplingThread::UpdateNextSampleTime( |
| 653 CollectionContext* collection) { | 663 CollectionContext* collection) { |
| 654 // This will keep a consistent average interval between samples but will | 664 // This will keep a consistent average interval between samples but will |
| 655 // result in constant series of acquisitions, thus nearly locking out the | 665 // result in constant series of acquisitions, thus nearly locking out the |
| 656 // target thread, if the interval is smaller than the time it takes to | 666 // target thread, if the interval is smaller than the time it takes to |
| 657 // actually acquire the sample. Anything sampling that quickly is going | 667 // actually acquire the sample. Anything sampling that quickly is going |
| 658 // to be a problem anyway so don't worry about it. | 668 // to be a problem anyway so don't worry about it. |
| 659 if (++collection->sample < collection->params.samples_per_burst) { | 669 if (++collection->sample < collection->params.samples_per_burst) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 } | 843 } |
| 834 | 844 |
| 835 bool operator<(const StackSamplingProfiler::Frame &a, | 845 bool operator<(const StackSamplingProfiler::Frame &a, |
| 836 const StackSamplingProfiler::Frame &b) { | 846 const StackSamplingProfiler::Frame &b) { |
| 837 return (a.module_index < b.module_index) || | 847 return (a.module_index < b.module_index) || |
| 838 (a.module_index == b.module_index && | 848 (a.module_index == b.module_index && |
| 839 a.instruction_pointer < b.instruction_pointer); | 849 a.instruction_pointer < b.instruction_pointer); |
| 840 } | 850 } |
| 841 | 851 |
| 842 } // namespace base | 852 } // namespace base |
| OLD | NEW |