| 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 <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 public: | 33 public: |
| 34 // Sets up a profiler and arranges for it to be deleted on its completed | 34 // Sets up a profiler and arranges for it to be deleted on its completed |
| 35 // callback. | 35 // callback. |
| 36 static void Run(PlatformThreadId thread_id, | 36 static void Run(PlatformThreadId thread_id, |
| 37 const StackSamplingProfiler::SamplingParams& params, | 37 const StackSamplingProfiler::SamplingParams& params, |
| 38 const StackSamplingProfiler::CompletedCallback& callback); | 38 const StackSamplingProfiler::CompletedCallback& callback); |
| 39 | 39 |
| 40 private: | 40 private: |
| 41 AsyncRunner(); | 41 AsyncRunner(); |
| 42 | 42 |
| 43 // Runs the callback and deletes the AsyncRunner instance. | 43 // Runs the callback and deletes the AsyncRunner instance. |profiles| is not |
| 44 // const& because it must be passed with std::move. |
| 44 static void RunCallbackAndDeleteInstance( | 45 static void RunCallbackAndDeleteInstance( |
| 45 std::unique_ptr<AsyncRunner> object_to_be_deleted, | 46 std::unique_ptr<AsyncRunner> object_to_be_deleted, |
| 46 const StackSamplingProfiler::CompletedCallback& callback, | 47 const StackSamplingProfiler::CompletedCallback& callback, |
| 47 scoped_refptr<SingleThreadTaskRunner> task_runner, | 48 scoped_refptr<SingleThreadTaskRunner> task_runner, |
| 48 const StackSamplingProfiler::CallStackProfiles& profiles); | 49 StackSamplingProfiler::CallStackProfiles profiles); |
| 49 | 50 |
| 50 std::unique_ptr<StackSamplingProfiler> profiler_; | 51 std::unique_ptr<StackSamplingProfiler> profiler_; |
| 51 | 52 |
| 52 DISALLOW_COPY_AND_ASSIGN(AsyncRunner); | 53 DISALLOW_COPY_AND_ASSIGN(AsyncRunner); |
| 53 }; | 54 }; |
| 54 | 55 |
| 55 // static | 56 // static |
| 56 void AsyncRunner::Run( | 57 void AsyncRunner::Run( |
| 57 PlatformThreadId thread_id, | 58 PlatformThreadId thread_id, |
| 58 const StackSamplingProfiler::SamplingParams& params, | 59 const StackSamplingProfiler::SamplingParams& params, |
| 59 const StackSamplingProfiler::CompletedCallback &callback) { | 60 const StackSamplingProfiler::CompletedCallback &callback) { |
| 60 std::unique_ptr<AsyncRunner> runner(new AsyncRunner); | 61 std::unique_ptr<AsyncRunner> runner(new AsyncRunner); |
| 61 AsyncRunner* temp_ptr = runner.get(); | 62 AsyncRunner* temp_ptr = runner.get(); |
| 62 temp_ptr->profiler_.reset( | 63 temp_ptr->profiler_.reset( |
| 63 new StackSamplingProfiler(thread_id, params, | 64 new StackSamplingProfiler(thread_id, params, |
| 64 Bind(&AsyncRunner::RunCallbackAndDeleteInstance, | 65 Bind(&AsyncRunner::RunCallbackAndDeleteInstance, |
| 65 Passed(&runner), callback, | 66 Passed(&runner), callback, |
| 66 ThreadTaskRunnerHandle::Get()))); | 67 ThreadTaskRunnerHandle::Get()))); |
| 67 // The callback won't be called until after Start(), so temp_ptr will still | 68 // The callback won't be called until after Start(), so temp_ptr will still |
| 68 // be valid here. | 69 // be valid here. |
| 69 temp_ptr->profiler_->Start(); | 70 temp_ptr->profiler_->Start(); |
| 70 } | 71 } |
| 71 | 72 |
| 72 AsyncRunner::AsyncRunner() {} | 73 AsyncRunner::AsyncRunner() {} |
| 73 | 74 |
| 74 void AsyncRunner::RunCallbackAndDeleteInstance( | 75 void AsyncRunner::RunCallbackAndDeleteInstance( |
| 75 std::unique_ptr<AsyncRunner> object_to_be_deleted, | 76 std::unique_ptr<AsyncRunner> object_to_be_deleted, |
| 76 const StackSamplingProfiler::CompletedCallback& callback, | 77 const StackSamplingProfiler::CompletedCallback& callback, |
| 77 scoped_refptr<SingleThreadTaskRunner> task_runner, | 78 scoped_refptr<SingleThreadTaskRunner> task_runner, |
| 78 const StackSamplingProfiler::CallStackProfiles& profiles) { | 79 StackSamplingProfiler::CallStackProfiles profiles) { |
| 79 callback.Run(profiles); | 80 callback.Run(std::move(profiles)); |
| 80 // Delete the instance on the original calling thread. | 81 // Delete the instance on the original calling thread. |
| 81 task_runner->DeleteSoon(FROM_HERE, object_to_be_deleted.release()); | 82 task_runner->DeleteSoon(FROM_HERE, object_to_be_deleted.release()); |
| 82 } | 83 } |
| 83 | 84 |
| 84 } // namespace | 85 } // namespace |
| 85 | 86 |
| 86 // StackSamplingProfiler::Module ---------------------------------------------- | 87 // StackSamplingProfiler::Module ---------------------------------------------- |
| 87 | 88 |
| 88 StackSamplingProfiler::Module::Module() : base_address(0u) {} | 89 StackSamplingProfiler::Module::Module() : base_address(0u) {} |
| 89 StackSamplingProfiler::Module::Module(uintptr_t base_address, | 90 StackSamplingProfiler::Module::Module(uintptr_t base_address, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 103 | 104 |
| 104 StackSamplingProfiler::Frame::Frame() | 105 StackSamplingProfiler::Frame::Frame() |
| 105 : instruction_pointer(0), module_index(kUnknownModuleIndex) { | 106 : instruction_pointer(0), module_index(kUnknownModuleIndex) { |
| 106 } | 107 } |
| 107 | 108 |
| 108 // StackSamplingProfiler::CallStackProfile ------------------------------------ | 109 // StackSamplingProfiler::CallStackProfile ------------------------------------ |
| 109 | 110 |
| 110 StackSamplingProfiler::CallStackProfile::CallStackProfile() {} | 111 StackSamplingProfiler::CallStackProfile::CallStackProfile() {} |
| 111 | 112 |
| 112 StackSamplingProfiler::CallStackProfile::CallStackProfile( | 113 StackSamplingProfiler::CallStackProfile::CallStackProfile( |
| 114 CallStackProfile&& other) = default; |
| 115 |
| 116 StackSamplingProfiler::CallStackProfile::~CallStackProfile() {} |
| 117 |
| 118 StackSamplingProfiler::CallStackProfile& |
| 119 StackSamplingProfiler::CallStackProfile::operator=(CallStackProfile&& other) = |
| 120 default; |
| 121 |
| 122 StackSamplingProfiler::CallStackProfile |
| 123 StackSamplingProfiler::CallStackProfile::CopyForTesting() const { |
| 124 return CallStackProfile(*this); |
| 125 } |
| 126 |
| 127 StackSamplingProfiler::CallStackProfile::CallStackProfile( |
| 113 const CallStackProfile& other) = default; | 128 const CallStackProfile& other) = default; |
| 114 | 129 |
| 115 StackSamplingProfiler::CallStackProfile::~CallStackProfile() {} | |
| 116 | |
| 117 // StackSamplingProfiler::SamplingThread -------------------------------------- | 130 // StackSamplingProfiler::SamplingThread -------------------------------------- |
| 118 | 131 |
| 119 StackSamplingProfiler::SamplingThread::SamplingThread( | 132 StackSamplingProfiler::SamplingThread::SamplingThread( |
| 120 std::unique_ptr<NativeStackSampler> native_sampler, | 133 std::unique_ptr<NativeStackSampler> native_sampler, |
| 121 const SamplingParams& params, | 134 const SamplingParams& params, |
| 122 const CompletedCallback& completed_callback) | 135 const CompletedCallback& completed_callback) |
| 123 : native_sampler_(std::move(native_sampler)), | 136 : native_sampler_(std::move(native_sampler)), |
| 124 params_(params), | 137 params_(params), |
| 125 stop_event_(WaitableEvent::ResetPolicy::AUTOMATIC, | 138 stop_event_(WaitableEvent::ResetPolicy::AUTOMATIC, |
| 126 WaitableEvent::InitialState::NOT_SIGNALED), | 139 WaitableEvent::InitialState::NOT_SIGNALED), |
| 127 completed_callback_(completed_callback) {} | 140 completed_callback_(completed_callback) {} |
| 128 | 141 |
| 129 StackSamplingProfiler::SamplingThread::~SamplingThread() {} | 142 StackSamplingProfiler::SamplingThread::~SamplingThread() {} |
| 130 | 143 |
| 131 void StackSamplingProfiler::SamplingThread::ThreadMain() { | 144 void StackSamplingProfiler::SamplingThread::ThreadMain() { |
| 132 PlatformThread::SetName("Chrome_SamplingProfilerThread"); | 145 PlatformThread::SetName("Chrome_SamplingProfilerThread"); |
| 133 | 146 |
| 134 // For now, just ignore any requests to profile while another profiler is | 147 // For now, just ignore any requests to profile while another profiler is |
| 135 // working. | 148 // working. |
| 136 if (!concurrent_profiling_lock.Get().Try()) | 149 if (!concurrent_profiling_lock.Get().Try()) |
| 137 return; | 150 return; |
| 138 | 151 |
| 139 CallStackProfiles profiles; | 152 CallStackProfiles profiles; |
| 140 CollectProfiles(&profiles); | 153 CollectProfiles(&profiles); |
| 141 concurrent_profiling_lock.Get().Release(); | 154 concurrent_profiling_lock.Get().Release(); |
| 142 completed_callback_.Run(profiles); | 155 completed_callback_.Run(std::move(profiles)); |
| 143 } | 156 } |
| 144 | 157 |
| 145 // Depending on how long the sampling takes and the length of the sampling | 158 // Depending on how long the sampling takes and the length of the sampling |
| 146 // interval, a burst of samples could take arbitrarily longer than | 159 // interval, a burst of samples could take arbitrarily longer than |
| 147 // samples_per_burst * sampling_interval. In this case, we (somewhat | 160 // samples_per_burst * sampling_interval. In this case, we (somewhat |
| 148 // arbitrarily) honor the number of samples requested rather than strictly | 161 // arbitrarily) honor the number of samples requested rather than strictly |
| 149 // adhering to the sampling intervals. Once we have established users for the | 162 // adhering to the sampling intervals. Once we have established users for the |
| 150 // StackSamplingProfiler and the collected data to judge, we may go the other | 163 // StackSamplingProfiler and the collected data to judge, we may go the other |
| 151 // way or make this behavior configurable. | 164 // way or make this behavior configurable. |
| 152 void StackSamplingProfiler::SamplingThread::CollectProfile( | 165 void StackSamplingProfiler::SamplingThread::CollectProfile( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if (stop_event_.TimedWait( | 209 if (stop_event_.TimedWait( |
| 197 std::max(params_.burst_interval - previous_elapsed_profile_time, | 210 std::max(params_.burst_interval - previous_elapsed_profile_time, |
| 198 TimeDelta()))) | 211 TimeDelta()))) |
| 199 return; | 212 return; |
| 200 } | 213 } |
| 201 | 214 |
| 202 CallStackProfile profile; | 215 CallStackProfile profile; |
| 203 bool was_stopped = false; | 216 bool was_stopped = false; |
| 204 CollectProfile(&profile, &previous_elapsed_profile_time, &was_stopped); | 217 CollectProfile(&profile, &previous_elapsed_profile_time, &was_stopped); |
| 205 if (!profile.samples.empty()) | 218 if (!profile.samples.empty()) |
| 206 profiles->push_back(profile); | 219 profiles->push_back(std::move(profile)); |
| 207 | 220 |
| 208 if (was_stopped) | 221 if (was_stopped) |
| 209 return; | 222 return; |
| 210 } | 223 } |
| 211 } | 224 } |
| 212 | 225 |
| 213 void StackSamplingProfiler::SamplingThread::Stop() { | 226 void StackSamplingProfiler::SamplingThread::Stop() { |
| 214 stop_event_.Signal(); | 227 stop_event_.Signal(); |
| 215 } | 228 } |
| 216 | 229 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 } | 303 } |
| 291 | 304 |
| 292 bool operator<(const StackSamplingProfiler::Frame &a, | 305 bool operator<(const StackSamplingProfiler::Frame &a, |
| 293 const StackSamplingProfiler::Frame &b) { | 306 const StackSamplingProfiler::Frame &b) { |
| 294 return (a.module_index < b.module_index) || | 307 return (a.module_index < b.module_index) || |
| 295 (a.module_index == b.module_index && | 308 (a.module_index == b.module_index && |
| 296 a.instruction_pointer < b.instruction_pointer); | 309 a.instruction_pointer < b.instruction_pointer); |
| 297 } | 310 } |
| 298 | 311 |
| 299 } // namespace base | 312 } // namespace base |
| OLD | NEW |