Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: base/trace_event/memory_dump_scheduler.cc

Issue 2736283003: [memory-infra] MemoryDumpScheduler follows config for time between dumps (Closed)
Patch Set: fix task runner check and rebase. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 15 matching lines...) Expand all
26 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) 26 scoped_refptr<SingleThreadTaskRunner> polling_task_runner)
27 : mdm_(mdm), polling_state_(polling_task_runner) {} 27 : mdm_(mdm), polling_state_(polling_task_runner) {}
28 28
29 MemoryDumpScheduler::~MemoryDumpScheduler() {} 29 MemoryDumpScheduler::~MemoryDumpScheduler() {}
30 30
31 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type, 31 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type,
32 MemoryDumpLevelOfDetail level_of_detail, 32 MemoryDumpLevelOfDetail level_of_detail,
33 uint32_t min_time_between_dumps_ms) { 33 uint32_t min_time_between_dumps_ms) {
34 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { 34 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) {
35 DCHECK(!periodic_state_.is_configured); 35 DCHECK(!periodic_state_.is_configured);
36 DCHECK(!polling_state_.is_configured); 36 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state);
37 DCHECK_NE(0u, min_time_between_dumps_ms); 37 DCHECK_NE(0u, min_time_between_dumps_ms);
38 38
39 polling_state_.level_of_detail = level_of_detail; 39 polling_state_.level_of_detail = level_of_detail;
40 polling_state_.min_polls_between_dumps = 40 polling_state_.min_polls_between_dumps =
41 (min_time_between_dumps_ms + polling_state_.polling_interval_ms - 1) / 41 (min_time_between_dumps_ms + polling_state_.polling_interval_ms - 1) /
42 polling_state_.polling_interval_ms; 42 polling_state_.polling_interval_ms;
43 polling_state_.is_configured = true; 43 polling_state_.current_state = PollingTriggerState::CONFIGURED;
44 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { 44 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
45 DCHECK(!polling_state_.is_configured); 45 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state);
46 periodic_state_.is_configured = true; 46 periodic_state_.is_configured = true;
47 DCHECK_NE(0u, min_time_between_dumps_ms); 47 DCHECK_NE(0u, min_time_between_dumps_ms);
48 switch (level_of_detail) { 48 switch (level_of_detail) {
49 case MemoryDumpLevelOfDetail::BACKGROUND: 49 case MemoryDumpLevelOfDetail::BACKGROUND:
50 break; 50 break;
51 case MemoryDumpLevelOfDetail::LIGHT: 51 case MemoryDumpLevelOfDetail::LIGHT:
52 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms); 52 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms);
53 periodic_state_.light_dump_period_ms = min_time_between_dumps_ms; 53 periodic_state_.light_dump_period_ms = min_time_between_dumps_ms;
54 break; 54 break;
55 case MemoryDumpLevelOfDetail::DETAILED: 55 case MemoryDumpLevelOfDetail::DETAILED:
(...skipping 20 matching lines...) Expand all
76 periodic_state_.min_timer_period_ms; 76 periodic_state_.min_timer_period_ms;
77 77
78 periodic_state_.dump_count = 0; 78 periodic_state_.dump_count = 0;
79 periodic_state_.timer.Start( 79 periodic_state_.timer.Start(
80 FROM_HERE, 80 FROM_HERE,
81 TimeDelta::FromMilliseconds(periodic_state_.min_timer_period_ms), 81 TimeDelta::FromMilliseconds(periodic_state_.min_timer_period_ms),
82 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); 82 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this)));
83 } 83 }
84 84
85 void MemoryDumpScheduler::NotifyPollingSupported() { 85 void MemoryDumpScheduler::NotifyPollingSupported() {
86 if (!polling_state_.is_configured || polling_state_.is_polling_enabled) 86 if (polling_state_.current_state != PollingTriggerState::CONFIGURED)
87 return; 87 return;
88 polling_state_.is_polling_enabled = true;
89 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i)
90 polling_state_.last_memory_totals_kb[i] = 0;
91 polling_state_.last_memory_totals_kb_index = 0;
92 polling_state_.num_polls_from_last_dump = 0;
93 polling_state_.last_dump_memory_total = 0;
94 88
95 if (!polling_state_.memory_increase_threshold) { 89 polling_state_.current_state = PollingTriggerState::ENABLED;
96 polling_state_.memory_increase_threshold = kDefaultMemoryIncreaseThreshold; 90 polling_state_.ResetTotals();
97 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
98 defined(OS_ANDROID)
99 // Set threshold to 1% of total system memory.
100 SystemMemoryInfoKB meminfo;
101 bool res = GetSystemMemoryInfo(&meminfo);
102 if (res)
103 polling_state_.memory_increase_threshold = (meminfo.total / 100) * 1024;
104 #endif
105 }
106 91
107 polling_state_.polling_task_runner->PostTask( 92 polling_state_.polling_task_runner->PostTask(
108 FROM_HERE, 93 FROM_HERE,
109 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this))); 94 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this)));
110 } 95 }
111 96
97 void MemoryDumpScheduler::NotifyDumpTriggered() {
98 if (polling_state_.polling_task_runner &&
99 polling_state_.polling_task_runner->RunsTasksOnCurrentThread()) {
100 polling_state_.polling_task_runner->PostTask(
101 FROM_HERE,
102 Bind(&MemoryDumpScheduler::NotifyDumpTriggered, Unretained(this)));
103 return;
104 }
105 if (polling_state_.current_state != PollingTriggerState::ENABLED)
106 return;
107
108 polling_state_.ResetTotals();
109 }
110
112 void MemoryDumpScheduler::DisableAllTriggers() { 111 void MemoryDumpScheduler::DisableAllTriggers() {
113 if (periodic_state_.timer.IsRunning()) 112 if (periodic_state_.timer.IsRunning())
114 periodic_state_.timer.Stop(); 113 periodic_state_.timer.Stop();
115 DisablePolling(); 114 DisablePolling();
116 } 115 }
117 116
118 void MemoryDumpScheduler::DisablePolling() { 117 void MemoryDumpScheduler::DisablePolling() {
119 if (ThreadTaskRunnerHandle::Get() != polling_state_.polling_task_runner) { 118 if (polling_state_.polling_task_runner->RunsTasksOnCurrentThread()) {
120 if (polling_state_.polling_task_runner->PostTask( 119 if (polling_state_.polling_task_runner->PostTask(
121 FROM_HERE, 120 FROM_HERE,
122 Bind(&MemoryDumpScheduler::DisablePolling, Unretained(this)))) 121 Bind(&MemoryDumpScheduler::DisablePolling, Unretained(this))))
123 return; 122 return;
124 } 123 }
125 polling_state_.is_polling_enabled = false; 124 polling_state_.current_state = PollingTriggerState::DISABLED;
126 polling_state_.is_configured = false;
127 polling_state_.polling_task_runner = nullptr; 125 polling_state_.polling_task_runner = nullptr;
128 } 126 }
129 127
130 // static 128 // static
131 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { 129 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) {
132 g_polling_interval_ms_for_testing = interval; 130 g_polling_interval_ms_for_testing = interval;
133 } 131 }
134 132
135 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { 133 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() {
136 return periodic_state_.timer.IsRunning(); 134 return periodic_state_.timer.IsRunning();
137 } 135 }
138 136
139 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { 137 void MemoryDumpScheduler::RequestPeriodicGlobalDump() {
140 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; 138 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND;
141 if (periodic_state_.light_dumps_rate > 0 && 139 if (periodic_state_.light_dumps_rate > 0 &&
142 periodic_state_.dump_count % periodic_state_.light_dumps_rate == 0) 140 periodic_state_.dump_count % periodic_state_.light_dumps_rate == 0)
143 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; 141 level_of_detail = MemoryDumpLevelOfDetail::LIGHT;
144 if (periodic_state_.heavy_dumps_rate > 0 && 142 if (periodic_state_.heavy_dumps_rate > 0 &&
145 periodic_state_.dump_count % periodic_state_.heavy_dumps_rate == 0) 143 periodic_state_.dump_count % periodic_state_.heavy_dumps_rate == 0)
146 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; 144 level_of_detail = MemoryDumpLevelOfDetail::DETAILED;
147 ++periodic_state_.dump_count; 145 ++periodic_state_.dump_count;
148 146
149 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); 147 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail);
150 } 148 }
151 149
152 void MemoryDumpScheduler::PollMemoryOnPollingThread() { 150 void MemoryDumpScheduler::PollMemoryOnPollingThread() {
153 if (!polling_state_.is_configured) 151 if (polling_state_.current_state != PollingTriggerState::ENABLED)
154 return; 152 return;
155 153
156 uint64_t polled_memory = 0; 154 uint64_t polled_memory = 0;
157 bool res = mdm_->PollFastMemoryTotal(&polled_memory); 155 bool res = mdm_->PollFastMemoryTotal(&polled_memory);
158 DCHECK(res); 156 DCHECK(res);
159 if (polling_state_.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { 157 if (polling_state_.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) {
160 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", 158 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB",
161 polled_memory / 1024 / 1024); 159 polled_memory / 1024 / 1024);
162 } 160 }
163 161
(...skipping 29 matching lines...) Expand all
193 } else if (polling_state_.min_polls_between_dumps > 191 } else if (polling_state_.min_polls_between_dumps >
194 polling_state_.num_polls_from_last_dump) { 192 polling_state_.num_polls_from_last_dump) {
195 return false; 193 return false;
196 } 194 }
197 195
198 int64_t increase_from_last_dump = 196 int64_t increase_from_last_dump =
199 current_memory_total - polling_state_.last_dump_memory_total; 197 current_memory_total - polling_state_.last_dump_memory_total;
200 should_dump |= 198 should_dump |=
201 increase_from_last_dump > polling_state_.memory_increase_threshold; 199 increase_from_last_dump > polling_state_.memory_increase_threshold;
202 should_dump |= IsCurrentSamplePeak(current_memory_total); 200 should_dump |= IsCurrentSamplePeak(current_memory_total);
203 if (should_dump) { 201 if (should_dump)
204 polling_state_.last_dump_memory_total = current_memory_total; 202 polling_state_.ResetTotals();
205 polling_state_.num_polls_from_last_dump = 0;
206 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i)
207 polling_state_.last_memory_totals_kb[i] = 0;
208 polling_state_.last_memory_totals_kb_index = 0;
209 }
210 return should_dump; 203 return should_dump;
211 } 204 }
212 205
213 bool MemoryDumpScheduler::IsCurrentSamplePeak( 206 bool MemoryDumpScheduler::IsCurrentSamplePeak(
214 uint64_t current_memory_total_bytes) { 207 uint64_t current_memory_total_bytes) {
215 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024; 208 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024;
216 polling_state_.last_memory_totals_kb_index = 209 polling_state_.last_memory_totals_kb_index =
217 (polling_state_.last_memory_totals_kb_index + 1) % 210 (polling_state_.last_memory_totals_kb_index + 1) %
218 PollingTriggerState::kMaxNumMemorySamples; 211 PollingTriggerState::kMaxNumMemorySamples;
219 uint64_t mean = 0; 212 uint64_t mean = 0;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 heavy_dumps_rate(0), 251 heavy_dumps_rate(0),
259 light_dump_period_ms(0), 252 light_dump_period_ms(0),
260 heavy_dump_period_ms(0) {} 253 heavy_dump_period_ms(0) {}
261 254
262 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { 255 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() {
263 DCHECK(!timer.IsRunning()); 256 DCHECK(!timer.IsRunning());
264 } 257 }
265 258
266 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState( 259 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState(
267 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) 260 scoped_refptr<SingleThreadTaskRunner> polling_task_runner)
268 : is_configured(false), 261 : current_state(DISABLED),
269 is_polling_enabled(false),
270 level_of_detail(MemoryDumpLevelOfDetail::FIRST), 262 level_of_detail(MemoryDumpLevelOfDetail::FIRST),
271 polling_task_runner(polling_task_runner), 263 polling_task_runner(polling_task_runner),
272 polling_interval_ms(g_polling_interval_ms_for_testing 264 polling_interval_ms(g_polling_interval_ms_for_testing
273 ? g_polling_interval_ms_for_testing 265 ? g_polling_interval_ms_for_testing
274 : kMemoryTotalsPollingInterval), 266 : kMemoryTotalsPollingInterval),
275 min_polls_between_dumps(0), 267 min_polls_between_dumps(0),
276 num_polls_from_last_dump(0), 268 num_polls_from_last_dump(-1),
277 last_dump_memory_total(0), 269 last_dump_memory_total(0),
278 memory_increase_threshold(0), 270 memory_increase_threshold(0),
279 last_memory_totals_kb_index(0) {} 271 last_memory_totals_kb_index(0) {}
280 272
281 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() { 273 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() {
282 DCHECK(!polling_task_runner); 274 DCHECK(!polling_task_runner);
283 } 275 }
284 276
277 void MemoryDumpScheduler::PollingTriggerState::ResetTotals() {
278 if (!memory_increase_threshold) {
279 memory_increase_threshold = kDefaultMemoryIncreaseThreshold;
280 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
281 defined(OS_ANDROID)
282 // Set threshold to 1% of total system memory.
283 SystemMemoryInfoKB meminfo;
284 bool res = GetSystemMemoryInfo(&meminfo);
285 if (res)
286 memory_increase_threshold = (meminfo.total / 100) * 1024;
287 #endif
288 }
289
290 // Update the |last_dump_memory_total|'s value from the totals if it's not
291 // first poll.
292 if (num_polls_from_last_dump >= 0 &&
293 last_memory_totals_kb[last_memory_totals_kb_index]) {
294 last_dump_memory_total =
295 last_memory_totals_kb[last_memory_totals_kb_index] * 1024;
296 }
297 num_polls_from_last_dump = 0;
298 for (uint32_t i = 0; i < kMaxNumMemorySamples; ++i)
299 last_memory_totals_kb[i] = 0;
300 last_memory_totals_kb_index = 0;
301 }
302
285 } // namespace trace_event 303 } // namespace trace_event
286 } // namespace base 304 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_dump_scheduler.h ('k') | services/resource_coordinator/memory/coordinator/coordinator_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698