| 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" |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 | 12 |
| 13 namespace base { | 13 namespace base { |
| 14 namespace trace_event { | 14 namespace trace_event { |
| 15 | 15 |
| 16 namespace { | 16 namespace { |
| 17 // Threshold on increase in memory from last dump beyond which a new dump must | 17 // Threshold on increase in memory from last dump beyond which a new dump must |
| 18 // be triggered. | 18 // be triggered. |
| 19 int64_t kDefaultMemoryIncreaseThreshold = 50 * 1024 * 1024; // 50MiB | 19 int64_t kDefaultMemoryIncreaseThreshold = 50 * 1024 * 1024; // 50MiB |
| 20 const uint32_t kMemoryTotalsPollingInterval = 25; | 20 const uint32_t kMemoryTotalsPollingInterval = 25; |
| 21 uint32_t g_polling_interval_ms_for_testing = 0; | 21 uint32_t g_polling_interval_ms_for_testing = 0; |
| 22 } // namespace | 22 } // namespace |
| 23 | 23 |
| 24 // static | 24 // static |
| 25 bool MemoryDumpScheduler::periodic_timer_disabled_for_testing_ = false; |
| 26 |
| 27 // static |
| 25 MemoryDumpScheduler* MemoryDumpScheduler::GetInstance() { | 28 MemoryDumpScheduler* MemoryDumpScheduler::GetInstance() { |
| 26 static MemoryDumpScheduler* instance = new MemoryDumpScheduler(); | 29 static MemoryDumpScheduler* instance = new MemoryDumpScheduler(); |
| 27 return instance; | 30 return instance; |
| 28 } | 31 } |
| 29 | 32 |
| 30 MemoryDumpScheduler::MemoryDumpScheduler() : mdm_(nullptr), is_setup_(false) {} | 33 MemoryDumpScheduler::MemoryDumpScheduler() : mdm_(nullptr), is_setup_(false) {} |
| 31 MemoryDumpScheduler::~MemoryDumpScheduler() {} | 34 MemoryDumpScheduler::~MemoryDumpScheduler() {} |
| 32 | 35 |
| 33 void MemoryDumpScheduler::Setup( | 36 void MemoryDumpScheduler::Setup( |
| 34 MemoryDumpManager* mdm, | 37 MemoryDumpManager* mdm, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 } | 84 } |
| 82 | 85 |
| 83 void MemoryDumpScheduler::EnablePeriodicTriggerIfNeeded() { | 86 void MemoryDumpScheduler::EnablePeriodicTriggerIfNeeded() { |
| 84 DCHECK(is_setup_); | 87 DCHECK(is_setup_); |
| 85 if (!periodic_state_->is_configured || periodic_state_->timer.IsRunning()) | 88 if (!periodic_state_->is_configured || periodic_state_->timer.IsRunning()) |
| 86 return; | 89 return; |
| 87 periodic_state_->light_dumps_rate = periodic_state_->light_dump_period_ms / | 90 periodic_state_->light_dumps_rate = periodic_state_->light_dump_period_ms / |
| 88 periodic_state_->min_timer_period_ms; | 91 periodic_state_->min_timer_period_ms; |
| 89 periodic_state_->heavy_dumps_rate = periodic_state_->heavy_dump_period_ms / | 92 periodic_state_->heavy_dumps_rate = periodic_state_->heavy_dump_period_ms / |
| 90 periodic_state_->min_timer_period_ms; | 93 periodic_state_->min_timer_period_ms; |
| 94 periodic_state_->dump_count = 0; |
| 95 periodic_state_->is_enabled_for_testing = true; |
| 91 | 96 |
| 92 periodic_state_->dump_count = 0; | 97 if (periodic_timer_disabled_for_testing_) |
| 98 return; |
| 99 polling_task_runner_->PostTask( |
| 100 FROM_HERE, Bind(&MemoryDumpScheduler::EnablePeriodicTimerOnPollingThread, |
| 101 Unretained(this))); |
| 102 } |
| 103 |
| 104 void MemoryDumpScheduler::EnablePeriodicTimerOnPollingThread() { |
| 93 periodic_state_->timer.Start( | 105 periodic_state_->timer.Start( |
| 94 FROM_HERE, | 106 FROM_HERE, |
| 95 TimeDelta::FromMilliseconds(periodic_state_->min_timer_period_ms), | 107 TimeDelta::FromMilliseconds(periodic_state_->min_timer_period_ms), |
| 96 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); | 108 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); |
| 97 } | 109 } |
| 98 | 110 |
| 99 void MemoryDumpScheduler::EnablePollingIfNeeded() { | 111 void MemoryDumpScheduler::EnablePollingIfNeeded() { |
| 100 DCHECK(is_setup_); | 112 DCHECK(is_setup_); |
| 101 if (polling_state_->current_state != PollingTriggerState::CONFIGURED) | 113 if (polling_state_->current_state != PollingTriggerState::CONFIGURED) |
| 102 return; | 114 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 120 | 132 |
| 121 if (!polling_state_ || | 133 if (!polling_state_ || |
| 122 polling_state_->current_state != PollingTriggerState::ENABLED) { | 134 polling_state_->current_state != PollingTriggerState::ENABLED) { |
| 123 return; | 135 return; |
| 124 } | 136 } |
| 125 | 137 |
| 126 polling_state_->ResetTotals(); | 138 polling_state_->ResetTotals(); |
| 127 } | 139 } |
| 128 | 140 |
| 129 void MemoryDumpScheduler::DisableAllTriggers() { | 141 void MemoryDumpScheduler::DisableAllTriggers() { |
| 142 if (polling_task_runner_) { |
| 143 polling_task_runner_->PostTask( |
| 144 FROM_HERE, Bind(&MemoryDumpScheduler::DisableTriggersOnPollingThread, |
| 145 Unretained(this))); |
| 146 polling_task_runner_ = nullptr; |
| 147 } |
| 148 is_setup_ = false; |
| 149 } |
| 150 |
| 151 void MemoryDumpScheduler::DisableTriggersOnPollingThread() { |
| 130 if (periodic_state_) { | 152 if (periodic_state_) { |
| 131 if (periodic_state_->timer.IsRunning()) | 153 if (periodic_state_->timer.IsRunning()) |
| 132 periodic_state_->timer.Stop(); | 154 periodic_state_->timer.Stop(); |
| 133 periodic_state_.reset(); | 155 periodic_state_.reset(); |
| 134 } | 156 } |
| 135 | 157 |
| 136 if (polling_task_runner_) { | |
| 137 DCHECK(polling_state_); | |
| 138 polling_task_runner_->PostTask( | |
| 139 FROM_HERE, Bind(&MemoryDumpScheduler::DisablePollingOnPollingThread, | |
| 140 Unretained(this))); | |
| 141 polling_task_runner_ = nullptr; | |
| 142 } | |
| 143 is_setup_ = false; | |
| 144 } | |
| 145 | |
| 146 void MemoryDumpScheduler::DisablePollingOnPollingThread() { | |
| 147 polling_state_->current_state = PollingTriggerState::DISABLED; | 158 polling_state_->current_state = PollingTriggerState::DISABLED; |
| 148 polling_state_.reset(); | 159 polling_state_.reset(); |
| 149 } | 160 } |
| 150 | 161 |
| 151 // static | 162 // static |
| 152 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { | 163 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { |
| 153 g_polling_interval_ms_for_testing = interval; | 164 g_polling_interval_ms_for_testing = interval; |
| 154 } | 165 } |
| 155 | 166 |
| 167 void MemoryDumpScheduler::DisablePeriodicTimerForTesting(bool disable) { |
| 168 periodic_timer_disabled_for_testing_ = disable; |
| 169 } |
| 170 |
| 156 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { | 171 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { |
| 157 return periodic_state_->timer.IsRunning(); | 172 return periodic_state_->is_enabled_for_testing; |
| 158 } | 173 } |
| 159 | 174 |
| 160 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { | 175 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { |
| 176 // In case it's called after timer stopped. |
| 177 if (!periodic_state_) |
| 178 return; |
| 179 |
| 161 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; | 180 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; |
| 162 if (periodic_state_->light_dumps_rate > 0 && | 181 if (periodic_state_->light_dumps_rate > 0 && |
| 163 periodic_state_->dump_count % periodic_state_->light_dumps_rate == 0) | 182 periodic_state_->dump_count % periodic_state_->light_dumps_rate == 0) |
| 164 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | 183 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
| 165 if (periodic_state_->heavy_dumps_rate > 0 && | 184 if (periodic_state_->heavy_dumps_rate > 0 && |
| 166 periodic_state_->dump_count % periodic_state_->heavy_dumps_rate == 0) | 185 periodic_state_->dump_count % periodic_state_->heavy_dumps_rate == 0) |
| 167 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; | 186 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
| 168 ++periodic_state_->dump_count; | 187 ++periodic_state_->dump_count; |
| 169 | 188 |
| 170 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 189 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| 171 } | 190 } |
| 172 | 191 |
| 173 void MemoryDumpScheduler::PollMemoryOnPollingThread() { | 192 void MemoryDumpScheduler::PollMemoryOnPollingThread() { |
| 174 if (polling_state_->current_state != PollingTriggerState::ENABLED) | 193 if (!polling_state_) |
| 175 return; | 194 return; |
| 176 | 195 |
| 177 uint64_t polled_memory = 0; | 196 uint64_t polled_memory = 0; |
| 178 bool res = mdm_->PollFastMemoryTotal(&polled_memory); | 197 bool res = mdm_->PollFastMemoryTotal(&polled_memory); |
| 179 DCHECK(res); | 198 DCHECK(res); |
| 180 if (polling_state_->level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { | 199 if (polling_state_->level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { |
| 181 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", | 200 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", |
| 182 polled_memory / 1024 / 1024); | 201 polled_memory / 1024 / 1024); |
| 183 } | 202 } |
| 184 | 203 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 (3.69 * 3.69 * variance); | 285 (3.69 * 3.69 * variance); |
| 267 } | 286 } |
| 268 | 287 |
| 269 MemoryDumpScheduler::PeriodicTriggerState::PeriodicTriggerState() | 288 MemoryDumpScheduler::PeriodicTriggerState::PeriodicTriggerState() |
| 270 : is_configured(false), | 289 : is_configured(false), |
| 271 dump_count(0), | 290 dump_count(0), |
| 272 min_timer_period_ms(std::numeric_limits<uint32_t>::max()), | 291 min_timer_period_ms(std::numeric_limits<uint32_t>::max()), |
| 273 light_dumps_rate(0), | 292 light_dumps_rate(0), |
| 274 heavy_dumps_rate(0), | 293 heavy_dumps_rate(0), |
| 275 light_dump_period_ms(0), | 294 light_dump_period_ms(0), |
| 276 heavy_dump_period_ms(0) {} | 295 heavy_dump_period_ms(0), |
| 296 is_enabled_for_testing(false) {} |
| 277 | 297 |
| 278 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { | 298 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { |
| 279 DCHECK(!timer.IsRunning()); | 299 DCHECK(!timer.IsRunning()); |
| 280 } | 300 } |
| 281 | 301 |
| 282 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState() | 302 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState() |
| 283 : current_state(DISABLED), | 303 : current_state(DISABLED), |
| 284 level_of_detail(MemoryDumpLevelOfDetail::FIRST), | 304 level_of_detail(MemoryDumpLevelOfDetail::FIRST), |
| 285 polling_interval_ms(g_polling_interval_ms_for_testing | 305 polling_interval_ms(g_polling_interval_ms_for_testing |
| 286 ? g_polling_interval_ms_for_testing | 306 ? g_polling_interval_ms_for_testing |
| (...skipping 30 matching lines...) Expand all Loading... |
| 317 last_memory_totals_kb[last_memory_totals_kb_index] * 1024; | 337 last_memory_totals_kb[last_memory_totals_kb_index] * 1024; |
| 318 } | 338 } |
| 319 num_polls_from_last_dump = 0; | 339 num_polls_from_last_dump = 0; |
| 320 for (uint32_t i = 0; i < kMaxNumMemorySamples; ++i) | 340 for (uint32_t i = 0; i < kMaxNumMemorySamples; ++i) |
| 321 last_memory_totals_kb[i] = 0; | 341 last_memory_totals_kb[i] = 0; |
| 322 last_memory_totals_kb_index = 0; | 342 last_memory_totals_kb_index = 0; |
| 323 } | 343 } |
| 324 | 344 |
| 325 } // namespace trace_event | 345 } // namespace trace_event |
| 326 } // namespace base | 346 } // namespace base |
| OLD | NEW |