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 |