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_dump_scheduler.h" | 5 #include "base/trace_event/memory_dump_scheduler.h" |
6 | 6 |
7 #include "base/process/process_metrics.h" | 7 #include "base/process/process_metrics.h" |
8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
9 #include "base/threading/thread_task_runner_handle.h" | 9 #include "base/threading/thread_task_runner_handle.h" |
10 #include "base/trace_event/memory_dump_manager.h" | 10 #include "base/trace_event/memory_dump_manager.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 #endif | 35 #endif |
36 } | 36 } |
37 | 37 |
38 MemoryDumpScheduler::~MemoryDumpScheduler() {} | 38 MemoryDumpScheduler::~MemoryDumpScheduler() {} |
39 | 39 |
40 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type, | 40 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type, |
41 MemoryDumpLevelOfDetail level_of_detail, | 41 MemoryDumpLevelOfDetail level_of_detail, |
42 uint32_t min_time_between_dumps_ms) { | 42 uint32_t min_time_between_dumps_ms) { |
43 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { | 43 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { |
44 DCHECK(!periodic_state_.is_configured); | 44 DCHECK(!periodic_state_.is_configured); |
45 DCHECK(!polling_state_.is_configured); | 45 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state); |
46 DCHECK_NE(0u, min_time_between_dumps_ms); | 46 DCHECK_NE(0u, min_time_between_dumps_ms); |
47 | 47 |
48 polling_state_.level_of_detail = level_of_detail; | 48 polling_state_.level_of_detail = level_of_detail; |
49 polling_state_.min_polls_between_dumps = | 49 polling_state_.min_polls_between_dumps = |
50 (min_time_between_dumps_ms + polling_state_.polling_interval_ms - 1) / | 50 (min_time_between_dumps_ms + polling_state_.polling_interval_ms - 1) / |
51 polling_state_.polling_interval_ms; | 51 polling_state_.polling_interval_ms; |
52 polling_state_.is_configured = true; | 52 polling_state_.current_state = PollingTriggerState::CONFIGURED; |
53 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { | 53 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { |
54 DCHECK(!polling_state_.is_configured); | 54 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state); |
55 periodic_state_.is_configured = true; | 55 periodic_state_.is_configured = true; |
56 DCHECK_NE(0u, min_time_between_dumps_ms); | 56 DCHECK_NE(0u, min_time_between_dumps_ms); |
57 switch (level_of_detail) { | 57 switch (level_of_detail) { |
58 case MemoryDumpLevelOfDetail::BACKGROUND: | 58 case MemoryDumpLevelOfDetail::BACKGROUND: |
59 break; | 59 break; |
60 case MemoryDumpLevelOfDetail::LIGHT: | 60 case MemoryDumpLevelOfDetail::LIGHT: |
61 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms); | 61 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms); |
62 periodic_state_.light_dump_period_ms = min_time_between_dumps_ms; | 62 periodic_state_.light_dump_period_ms = min_time_between_dumps_ms; |
63 break; | 63 break; |
64 case MemoryDumpLevelOfDetail::DETAILED: | 64 case MemoryDumpLevelOfDetail::DETAILED: |
(...skipping 20 matching lines...) Expand all Loading... | |
85 periodic_state_.min_timer_period_ms; | 85 periodic_state_.min_timer_period_ms; |
86 | 86 |
87 periodic_state_.dump_count = 0; | 87 periodic_state_.dump_count = 0; |
88 periodic_state_.timer.Start( | 88 periodic_state_.timer.Start( |
89 FROM_HERE, | 89 FROM_HERE, |
90 TimeDelta::FromMilliseconds(periodic_state_.min_timer_period_ms), | 90 TimeDelta::FromMilliseconds(periodic_state_.min_timer_period_ms), |
91 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); | 91 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); |
92 } | 92 } |
93 | 93 |
94 void MemoryDumpScheduler::NotifyPollingSupported() { | 94 void MemoryDumpScheduler::NotifyPollingSupported() { |
95 if (!polling_state_.is_configured || polling_state_.is_polling_enabled) | 95 if (polling_state_.current_state != PollingTriggerState::CONFIGURED) |
96 return; | 96 return; |
97 polling_state_.is_polling_enabled = true; | 97 polling_state_.current_state = PollingTriggerState::ENABLED; |
98 for (uint32_t i = 0; | 98 |
99 i < PollingTriggerState::kNumTotalsTrackedForPeakDetection; ++i) { | 99 polling_state_.ResetTotals(); |
100 polling_state_.last_memory_totals_kb[i] = 0; | |
101 } | |
102 polling_state_.last_memory_totals_kb_index = 0; | |
103 polling_state_.num_polls_from_last_dump = 0; | |
104 polling_state_.last_dump_memory_total = 0; | |
105 polling_state_.polling_task_runner->PostTask( | 100 polling_state_.polling_task_runner->PostTask( |
106 FROM_HERE, | 101 FROM_HERE, |
107 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this))); | 102 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this))); |
108 } | 103 } |
109 | 104 |
105 void MemoryDumpScheduler::NotifyDumpTriggered() { | |
106 if (polling_state_.polling_task_runner && | |
107 ThreadTaskRunnerHandle::Get() != polling_state_.polling_task_runner) { | |
Primiano Tucci (use gerrit)
2017/03/10 10:35:39
do you really want to compare the TaskRunnerHandle
ssid
2017/03/10 23:51:10
Yes my bad. Fixed it.
| |
108 polling_state_.polling_task_runner->PostTask( | |
109 FROM_HERE, | |
110 Bind(&MemoryDumpScheduler::NotifyDumpTriggered, Unretained(this))); | |
Primiano Tucci (use gerrit)
2017/03/10 10:35:39
Also I just realized that these Unretained aren't
ssid
2017/03/10 14:57:37
The reason why the unretained should be safe here
| |
111 return; | |
112 } | |
113 if (polling_state_.current_state != PollingTriggerState::ENABLED) | |
114 return; | |
115 | |
116 polling_state_.ResetTotals(); | |
117 } | |
118 | |
110 void MemoryDumpScheduler::DisableAllTriggers() { | 119 void MemoryDumpScheduler::DisableAllTriggers() { |
111 if (periodic_state_.timer.IsRunning()) | 120 if (periodic_state_.timer.IsRunning()) |
112 periodic_state_.timer.Stop(); | 121 periodic_state_.timer.Stop(); |
113 DisablePolling(); | 122 DisablePolling(); |
114 } | 123 } |
115 | 124 |
116 void MemoryDumpScheduler::DisablePolling() { | 125 void MemoryDumpScheduler::DisablePolling() { |
117 if (ThreadTaskRunnerHandle::Get() != polling_state_.polling_task_runner) { | 126 if (ThreadTaskRunnerHandle::Get() != polling_state_.polling_task_runner) { |
118 if (polling_state_.polling_task_runner->PostTask( | 127 if (polling_state_.polling_task_runner->PostTask( |
119 FROM_HERE, | 128 FROM_HERE, |
120 Bind(&MemoryDumpScheduler::DisablePolling, Unretained(this)))) | 129 Bind(&MemoryDumpScheduler::DisablePolling, Unretained(this)))) |
121 return; | 130 return; |
122 } | 131 } |
123 polling_state_.is_polling_enabled = false; | 132 polling_state_.current_state = PollingTriggerState::DISABLED; |
124 polling_state_.is_configured = false; | |
125 polling_state_.polling_task_runner = nullptr; | 133 polling_state_.polling_task_runner = nullptr; |
126 } | 134 } |
127 | 135 |
128 // static | 136 // static |
129 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { | 137 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { |
130 g_polling_interval_ms_for_testing = interval; | 138 g_polling_interval_ms_for_testing = interval; |
131 } | 139 } |
132 | 140 |
133 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { | 141 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { |
134 return periodic_state_.timer.IsRunning(); | 142 return periodic_state_.timer.IsRunning(); |
135 } | 143 } |
136 | 144 |
137 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { | 145 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { |
138 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; | 146 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; |
139 if (periodic_state_.light_dumps_rate > 0 && | 147 if (periodic_state_.light_dumps_rate > 0 && |
140 periodic_state_.dump_count % periodic_state_.light_dumps_rate == 0) | 148 periodic_state_.dump_count % periodic_state_.light_dumps_rate == 0) |
141 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | 149 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
142 if (periodic_state_.heavy_dumps_rate > 0 && | 150 if (periodic_state_.heavy_dumps_rate > 0 && |
143 periodic_state_.dump_count % periodic_state_.heavy_dumps_rate == 0) | 151 periodic_state_.dump_count % periodic_state_.heavy_dumps_rate == 0) |
144 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; | 152 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
145 ++periodic_state_.dump_count; | 153 ++periodic_state_.dump_count; |
146 | 154 |
147 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 155 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
148 } | 156 } |
149 | 157 |
150 void MemoryDumpScheduler::PollMemoryOnPollingThread() { | 158 void MemoryDumpScheduler::PollMemoryOnPollingThread() { |
151 if (!polling_state_.is_configured) | 159 if (polling_state_.current_state != PollingTriggerState::ENABLED) |
152 return; | 160 return; |
153 | 161 |
154 uint64_t polled_memory = 0; | 162 uint64_t polled_memory = 0; |
155 bool res = mdm_->PollFastMemoryTotal(&polled_memory); | 163 bool res = mdm_->PollFastMemoryTotal(&polled_memory); |
156 DCHECK(res); | 164 DCHECK(res); |
157 if (polling_state_.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { | 165 if (polling_state_.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { |
158 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", | 166 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", |
159 polled_memory / 1024 / 1024); | 167 polled_memory / 1024 / 1024); |
160 } | 168 } |
161 | 169 |
(...skipping 29 matching lines...) Expand all Loading... | |
191 } else if (polling_state_.min_polls_between_dumps > | 199 } else if (polling_state_.min_polls_between_dumps > |
192 polling_state_.num_polls_from_last_dump) { | 200 polling_state_.num_polls_from_last_dump) { |
193 return false; | 201 return false; |
194 } | 202 } |
195 | 203 |
196 int64_t increase_from_last_dump = | 204 int64_t increase_from_last_dump = |
197 current_memory_total - polling_state_.last_dump_memory_total; | 205 current_memory_total - polling_state_.last_dump_memory_total; |
198 should_dump |= | 206 should_dump |= |
199 increase_from_last_dump > polling_state_.memory_increase_threshold; | 207 increase_from_last_dump > polling_state_.memory_increase_threshold; |
200 should_dump |= IsCurrentSamplePeak(current_memory_total); | 208 should_dump |= IsCurrentSamplePeak(current_memory_total); |
201 if (should_dump) { | 209 if (should_dump) |
202 polling_state_.last_dump_memory_total = current_memory_total; | 210 polling_state_.ResetTotals(); |
203 polling_state_.num_polls_from_last_dump = 0; | |
204 for (uint32_t i = 0; | |
205 i < PollingTriggerState::kNumTotalsTrackedForPeakDetection; ++i) { | |
206 polling_state_.last_memory_totals_kb[i] = 0; | |
207 } | |
208 polling_state_.last_memory_totals_kb_index = 0; | |
209 } | |
210 return should_dump; | 211 return should_dump; |
211 } | 212 } |
212 | 213 |
213 bool MemoryDumpScheduler::IsCurrentSamplePeak( | 214 bool MemoryDumpScheduler::IsCurrentSamplePeak( |
214 uint64_t current_memory_total_bytes) { | 215 uint64_t current_memory_total_bytes) { |
215 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024; | 216 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024; |
216 polling_state_.last_memory_totals_kb_index = | 217 polling_state_.last_memory_totals_kb_index = |
217 (polling_state_.last_memory_totals_kb_index + 1) % | 218 (polling_state_.last_memory_totals_kb_index + 1) % |
218 PollingTriggerState::kNumTotalsTrackedForPeakDetection; | 219 PollingTriggerState::kNumTotalsTrackedForPeakDetection; |
219 uint64_t mean = 0; | 220 uint64_t mean = 0; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 heavy_dumps_rate(0), | 261 heavy_dumps_rate(0), |
261 light_dump_period_ms(0), | 262 light_dump_period_ms(0), |
262 heavy_dump_period_ms(0) {} | 263 heavy_dump_period_ms(0) {} |
263 | 264 |
264 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { | 265 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { |
265 DCHECK(!timer.IsRunning()); | 266 DCHECK(!timer.IsRunning()); |
266 } | 267 } |
267 | 268 |
268 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState( | 269 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState( |
269 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) | 270 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) |
270 : is_configured(false), | 271 : current_state(DISABLED), |
271 is_polling_enabled(false), | |
272 level_of_detail(MemoryDumpLevelOfDetail::FIRST), | 272 level_of_detail(MemoryDumpLevelOfDetail::FIRST), |
273 polling_task_runner(polling_task_runner), | 273 polling_task_runner(polling_task_runner), |
274 polling_interval_ms(g_polling_interval_ms_for_testing | 274 polling_interval_ms(g_polling_interval_ms_for_testing |
275 ? g_polling_interval_ms_for_testing | 275 ? g_polling_interval_ms_for_testing |
276 : kMemoryTotalsPollingInterval), | 276 : kMemoryTotalsPollingInterval), |
277 min_polls_between_dumps(0), | 277 min_polls_between_dumps(0), |
278 num_polls_from_last_dump(0), | 278 num_polls_from_last_dump(0), |
279 last_dump_memory_total(0), | 279 last_dump_memory_total(0), |
280 memory_increase_threshold(kDefaultMemoryIncreaseThreshold), | 280 memory_increase_threshold(kDefaultMemoryIncreaseThreshold), |
281 last_memory_totals_kb_index(0) {} | 281 last_memory_totals_kb_index(0) {} |
282 | 282 |
283 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() { | 283 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() { |
284 DCHECK(!polling_task_runner); | 284 DCHECK(!polling_task_runner); |
285 } | 285 } |
286 | 286 |
287 void MemoryDumpScheduler::PollingTriggerState::ResetTotals() { | |
288 if (last_memory_totals_kb_index) { | |
289 last_dump_memory_total = | |
290 last_memory_totals_kb[last_memory_totals_kb_index] * 1024; | |
291 } | |
292 num_polls_from_last_dump = 0; | |
293 for (uint32_t i = 0; i < kNumTotalsTrackedForPeakDetection; ++i) | |
294 last_memory_totals_kb[i] = 0; | |
295 last_memory_totals_kb_index = 0; | |
296 } | |
297 | |
287 } // namespace trace_event | 298 } // namespace trace_event |
288 } // namespace base | 299 } // namespace base |
OLD | NEW |