| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/trace_event/memory_peak_detector.h" | 5 #include "base/trace_event/memory_peak_detector.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 // Fallback, mostly for test environments where AmountOfPhysicalMemory() is | 61 // Fallback, mostly for test environments where AmountOfPhysicalMemory() is |
| 62 // broken. | 62 // broken. |
| 63 static_threshold_bytes_ = | 63 static_threshold_bytes_ = |
| 64 std::max(static_threshold_bytes_, static_cast<uint64_t>(5 * 1024 * 1024)); | 64 std::max(static_threshold_bytes_, static_cast<uint64_t>(5 * 1024 * 1024)); |
| 65 } | 65 } |
| 66 | 66 |
| 67 void MemoryPeakDetector::TearDown() { | 67 void MemoryPeakDetector::TearDown() { |
| 68 if (task_runner_) { | 68 if (task_runner_) { |
| 69 task_runner_->PostTask( | 69 task_runner_->PostTask( |
| 70 FROM_HERE, | 70 FROM_HERE, |
| 71 Bind(&MemoryPeakDetector::TearDownInternal, Unretained(this))); | 71 BindOnce(&MemoryPeakDetector::TearDownInternal, Unretained(this))); |
| 72 } | 72 } |
| 73 task_runner_ = nullptr; | 73 task_runner_ = nullptr; |
| 74 } | 74 } |
| 75 | 75 |
| 76 void MemoryPeakDetector::Start(MemoryPeakDetector::Config config) { | 76 void MemoryPeakDetector::Start(MemoryPeakDetector::Config config) { |
| 77 if (!config.polling_interval_ms) { | 77 if (!config.polling_interval_ms) { |
| 78 NOTREACHED(); | 78 NOTREACHED(); |
| 79 return; | 79 return; |
| 80 } | 80 } |
| 81 task_runner_->PostTask(FROM_HERE, Bind(&MemoryPeakDetector::StartInternal, | 81 task_runner_->PostTask(FROM_HERE, BindOnce(&MemoryPeakDetector::StartInternal, |
| 82 Unretained(this), config)); | 82 Unretained(this), config)); |
| 83 } | 83 } |
| 84 | 84 |
| 85 void MemoryPeakDetector::Stop() { | 85 void MemoryPeakDetector::Stop() { |
| 86 task_runner_->PostTask( | 86 task_runner_->PostTask( |
| 87 FROM_HERE, Bind(&MemoryPeakDetector::StopInternal, Unretained(this))); | 87 FROM_HERE, BindOnce(&MemoryPeakDetector::StopInternal, Unretained(this))); |
| 88 } | 88 } |
| 89 | 89 |
| 90 void MemoryPeakDetector::Throttle() { | 90 void MemoryPeakDetector::Throttle() { |
| 91 if (!task_runner_) | 91 if (!task_runner_) |
| 92 return; // Can be called before Setup(). | 92 return; // Can be called before Setup(). |
| 93 task_runner_->PostTask( | 93 task_runner_->PostTask( |
| 94 FROM_HERE, Bind(&MemoryPeakDetector::ResetPollHistory, Unretained(this), | 94 FROM_HERE, BindOnce(&MemoryPeakDetector::ResetPollHistory, |
| 95 true /* keep_last_sample */)); | 95 Unretained(this), true /* keep_last_sample */)); |
| 96 } | 96 } |
| 97 | 97 |
| 98 void MemoryPeakDetector::NotifyMemoryDumpProvidersChanged() { | 98 void MemoryPeakDetector::NotifyMemoryDumpProvidersChanged() { |
| 99 if (!task_runner_) | 99 if (!task_runner_) |
| 100 return; // Can be called before Setup(). | 100 return; // Can be called before Setup(). |
| 101 task_runner_->PostTask( | 101 task_runner_->PostTask( |
| 102 FROM_HERE, | 102 FROM_HERE, |
| 103 Bind(&MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded, | 103 BindOnce(&MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded, |
| 104 Unretained(this))); | 104 Unretained(this))); |
| 105 } | 105 } |
| 106 | 106 |
| 107 void MemoryPeakDetector::StartInternal(MemoryPeakDetector::Config config) { | 107 void MemoryPeakDetector::StartInternal(MemoryPeakDetector::Config config) { |
| 108 DCHECK_EQ(DISABLED, state_); | 108 DCHECK_EQ(DISABLED, state_); |
| 109 state_ = ENABLED; | 109 state_ = ENABLED; |
| 110 config_ = config; | 110 config_ = config; |
| 111 ResetPollHistory(); | 111 ResetPollHistory(); |
| 112 | 112 |
| 113 // If there are any dump providers available, | 113 // If there are any dump providers available, |
| 114 // NotifyMemoryDumpProvidersChanged will fetch them and start the polling. | 114 // NotifyMemoryDumpProvidersChanged will fetch them and start the polling. |
| 115 // Otherwise this will remain in the ENABLED state and the actual polling | 115 // Otherwise this will remain in the ENABLED state and the actual polling |
| 116 // will start on the next call to | 116 // will start on the next call to |
| 117 // ReloadDumpProvidersAndStartPollingIfNeeded(). | 117 // ReloadDumpProvidersAndStartPollingIfNeeded(). |
| 118 // Depending on the sandbox model, it is possible that no polling-capable | 118 // Depending on the sandbox model, it is possible that no polling-capable |
| 119 // dump providers will be ever available. | 119 // dump providers will be ever available. |
| 120 ReloadDumpProvidersAndStartPollingIfNeeded(); | 120 ReloadDumpProvidersAndStartPollingIfNeeded(); |
| 121 } | 121 } |
| 122 | 122 |
| 123 void MemoryPeakDetector::StopInternal() { | 123 void MemoryPeakDetector::StopInternal() { |
| 124 DCHECK_NE(NOT_INITIALIZED, state_); | 124 DCHECK_NE(NOT_INITIALIZED, state_); |
| 125 state_ = DISABLED; | 125 state_ = DISABLED; |
| 126 ++generation_; | 126 ++generation_; |
| 127 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp_info : dump_providers_) |
| 128 mdp_info->dump_provider->SuspendFastMemoryPolling(); |
| 127 dump_providers_.clear(); | 129 dump_providers_.clear(); |
| 128 } | 130 } |
| 129 | 131 |
| 130 void MemoryPeakDetector::TearDownInternal() { | 132 void MemoryPeakDetector::TearDownInternal() { |
| 131 StopInternal(); | 133 StopInternal(); |
| 132 get_dump_providers_function_.Reset(); | 134 get_dump_providers_function_.Reset(); |
| 133 on_peak_detected_callback_.Reset(); | 135 on_peak_detected_callback_.Reset(); |
| 134 state_ = NOT_INITIALIZED; | 136 state_ = NOT_INITIALIZED; |
| 135 } | 137 } |
| 136 | 138 |
| 137 void MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded() { | 139 void MemoryPeakDetector::ReloadDumpProvidersAndStartPollingIfNeeded() { |
| 138 if (state_ == DISABLED || state_ == NOT_INITIALIZED) | 140 if (state_ == DISABLED || state_ == NOT_INITIALIZED) |
| 139 return; // Start() will re-fetch the MDP list later. | 141 return; // Start() will re-fetch the MDP list later. |
| 140 | 142 |
| 141 DCHECK((state_ == RUNNING && !dump_providers_.empty()) || | 143 DCHECK((state_ == RUNNING && !dump_providers_.empty()) || |
| 142 (state_ == ENABLED && dump_providers_.empty())); | 144 (state_ == ENABLED && dump_providers_.empty())); |
| 143 | 145 |
| 144 dump_providers_.clear(); | 146 dump_providers_.clear(); |
| 145 | 147 |
| 146 // This is really MemoryDumpManager::GetDumpProvidersForPolling, % testing. | 148 // This is really MemoryDumpManager::GetDumpProvidersForPolling, % testing. |
| 147 get_dump_providers_function_.Run(&dump_providers_); | 149 get_dump_providers_function_.Run(&dump_providers_); |
| 148 | 150 |
| 149 if (state_ == ENABLED && !dump_providers_.empty()) { | 151 if (state_ == ENABLED && !dump_providers_.empty()) { |
| 150 // It's now time to start polling for realz. | 152 // It's now time to start polling for realz. |
| 151 state_ = RUNNING; | 153 state_ = RUNNING; |
| 152 task_runner_->PostTask(FROM_HERE, | 154 task_runner_->PostTask( |
| 153 Bind(&MemoryPeakDetector::PollMemoryAndDetectPeak, | 155 FROM_HERE, BindOnce(&MemoryPeakDetector::PollMemoryAndDetectPeak, |
| 154 Unretained(this), ++generation_)); | 156 Unretained(this), ++generation_)); |
| 155 } else if (state_ == RUNNING && dump_providers_.empty()) { | 157 } else if (state_ == RUNNING && dump_providers_.empty()) { |
| 156 // Will cause the next PollMemoryAndDetectPeak() task to early return. | 158 // Will cause the next PollMemoryAndDetectPeak() task to early return. |
| 157 state_ = ENABLED; | 159 state_ = ENABLED; |
| 158 ++generation_; | 160 ++generation_; |
| 159 } | 161 } |
| 160 } | 162 } |
| 161 | 163 |
| 162 void MemoryPeakDetector::PollMemoryAndDetectPeak(uint32_t expected_generation) { | 164 void MemoryPeakDetector::PollMemoryAndDetectPeak(uint32_t expected_generation) { |
| 163 if (state_ != RUNNING || generation_ != expected_generation) | 165 if (state_ != RUNNING || generation_ != expected_generation) |
| 164 return; | 166 return; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 194 is_peak = | 196 is_peak = |
| 195 diff_from_last_dump > static_cast<int64_t>(static_threshold_bytes_); | 197 diff_from_last_dump > static_cast<int64_t>(static_threshold_bytes_); |
| 196 | 198 |
| 197 if (!is_peak) | 199 if (!is_peak) |
| 198 is_peak = DetectPeakUsingSlidingWindowStddev(polled_mem_bytes); | 200 is_peak = DetectPeakUsingSlidingWindowStddev(polled_mem_bytes); |
| 199 } | 201 } |
| 200 | 202 |
| 201 DCHECK_GT(config_.polling_interval_ms, 0u); | 203 DCHECK_GT(config_.polling_interval_ms, 0u); |
| 202 SequencedTaskRunnerHandle::Get()->PostDelayedTask( | 204 SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| 203 FROM_HERE, | 205 FROM_HERE, |
| 204 Bind(&MemoryPeakDetector::PollMemoryAndDetectPeak, Unretained(this), | 206 BindOnce(&MemoryPeakDetector::PollMemoryAndDetectPeak, Unretained(this), |
| 205 expected_generation), | 207 expected_generation), |
| 206 TimeDelta::FromMilliseconds(config_.polling_interval_ms)); | 208 TimeDelta::FromMilliseconds(config_.polling_interval_ms)); |
| 207 | 209 |
| 208 if (!is_peak) | 210 if (!is_peak) |
| 209 return; | 211 return; |
| 210 TRACE_EVENT_INSTANT1(MemoryDumpManager::kTraceCategory, | 212 TRACE_EVENT_INSTANT1(MemoryDumpManager::kTraceCategory, |
| 211 "Peak memory detected", TRACE_EVENT_SCOPE_PROCESS, | 213 "Peak memory detected", TRACE_EVENT_SCOPE_PROCESS, |
| 212 "PolledMemoryMB", polled_mem_bytes / 1024 / 1024); | 214 "PolledMemoryMB", polled_mem_bytes / 1024 / 1024); |
| 213 ResetPollHistory(true /* keep_last_sample */); | 215 ResetPollHistory(true /* keep_last_sample */); |
| 214 last_dump_memory_total_ = polled_mem_bytes; | 216 last_dump_memory_total_ = polled_mem_bytes; |
| 215 on_peak_detected_callback_.Run(); | 217 on_peak_detected_callback_.Run(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 config_.polling_interval_ms; | 266 config_.polling_interval_ms; |
| 265 } | 267 } |
| 266 } | 268 } |
| 267 | 269 |
| 268 void MemoryPeakDetector::SetStaticThresholdForTesting( | 270 void MemoryPeakDetector::SetStaticThresholdForTesting( |
| 269 uint64_t static_threshold_bytes) { | 271 uint64_t static_threshold_bytes) { |
| 270 DCHECK_EQ(DISABLED, state_); | 272 DCHECK_EQ(DISABLED, state_); |
| 271 static_threshold_bytes_ = static_threshold_bytes; | 273 static_threshold_bytes_ = static_threshold_bytes; |
| 272 } | 274 } |
| 273 | 275 |
| 276 MemoryPeakDetector::MemoryPeakDetector::Config::Config() |
| 277 : Config(0, 0, false) {} |
| 278 |
| 279 MemoryPeakDetector::MemoryPeakDetector::Config::Config( |
| 280 uint32_t polling_interval_ms, |
| 281 uint32_t min_time_between_peaks_ms, |
| 282 bool enable_verbose_poll_tracing) |
| 283 : polling_interval_ms(polling_interval_ms), |
| 284 min_time_between_peaks_ms(min_time_between_peaks_ms), |
| 285 enable_verbose_poll_tracing(enable_verbose_poll_tracing) {} |
| 286 |
| 274 } // namespace trace_event | 287 } // namespace trace_event |
| 275 } // namespace base | 288 } // namespace base |
| OLD | NEW |