| 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 MemoryDumpScheduler::MemoryDumpScheduler( | 24 // static |
| 25 MemoryDumpScheduler* MemoryDumpScheduler::GetInstance() { |
| 26 static MemoryDumpScheduler* instance = new MemoryDumpScheduler(); |
| 27 return instance; |
| 28 } |
| 29 |
| 30 MemoryDumpScheduler::MemoryDumpScheduler() : mdm_(nullptr), is_setup_(false) {} |
| 31 MemoryDumpScheduler::~MemoryDumpScheduler() {} |
| 32 |
| 33 void MemoryDumpScheduler::Setup( |
| 25 MemoryDumpManager* mdm, | 34 MemoryDumpManager* mdm, |
| 26 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) | 35 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) { |
| 27 : mdm_(mdm), polling_state_(polling_task_runner) {} | 36 mdm_ = mdm; |
| 28 | 37 polling_task_runner_ = polling_task_runner; |
| 29 MemoryDumpScheduler::~MemoryDumpScheduler() {} | 38 periodic_state_.reset(new PeriodicTriggerState); |
| 39 polling_state_.reset(new PollingTriggerState); |
| 40 is_setup_ = true; |
| 41 } |
| 30 | 42 |
| 31 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type, | 43 void MemoryDumpScheduler::AddTrigger(MemoryDumpType trigger_type, |
| 32 MemoryDumpLevelOfDetail level_of_detail, | 44 MemoryDumpLevelOfDetail level_of_detail, |
| 33 uint32_t min_time_between_dumps_ms) { | 45 uint32_t min_time_between_dumps_ms) { |
| 46 DCHECK(is_setup_); |
| 34 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { | 47 if (trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { |
| 35 DCHECK(!periodic_state_.is_configured); | 48 DCHECK(!periodic_state_->is_configured); |
| 36 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state); | 49 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_->current_state); |
| 37 DCHECK_NE(0u, min_time_between_dumps_ms); | 50 DCHECK_NE(0u, min_time_between_dumps_ms); |
| 38 | 51 |
| 39 polling_state_.level_of_detail = level_of_detail; | 52 polling_state_->level_of_detail = level_of_detail; |
| 40 polling_state_.min_polls_between_dumps = | 53 polling_state_->min_polls_between_dumps = |
| 41 (min_time_between_dumps_ms + polling_state_.polling_interval_ms - 1) / | 54 (min_time_between_dumps_ms + polling_state_->polling_interval_ms - 1) / |
| 42 polling_state_.polling_interval_ms; | 55 polling_state_->polling_interval_ms; |
| 43 polling_state_.current_state = PollingTriggerState::CONFIGURED; | 56 polling_state_->current_state = PollingTriggerState::CONFIGURED; |
| 44 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { | 57 } else if (trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { |
| 45 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_.current_state); | 58 DCHECK_EQ(PollingTriggerState::DISABLED, polling_state_->current_state); |
| 46 periodic_state_.is_configured = true; | 59 periodic_state_->is_configured = true; |
| 47 DCHECK_NE(0u, min_time_between_dumps_ms); | 60 DCHECK_NE(0u, min_time_between_dumps_ms); |
| 48 switch (level_of_detail) { | 61 switch (level_of_detail) { |
| 49 case MemoryDumpLevelOfDetail::BACKGROUND: | 62 case MemoryDumpLevelOfDetail::BACKGROUND: |
| 50 break; | 63 break; |
| 51 case MemoryDumpLevelOfDetail::LIGHT: | 64 case MemoryDumpLevelOfDetail::LIGHT: |
| 52 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms); | 65 DCHECK_EQ(0u, periodic_state_->light_dump_period_ms); |
| 53 periodic_state_.light_dump_period_ms = min_time_between_dumps_ms; | 66 periodic_state_->light_dump_period_ms = min_time_between_dumps_ms; |
| 54 break; | 67 break; |
| 55 case MemoryDumpLevelOfDetail::DETAILED: | 68 case MemoryDumpLevelOfDetail::DETAILED: |
| 56 DCHECK_EQ(0u, periodic_state_.heavy_dump_period_ms); | 69 DCHECK_EQ(0u, periodic_state_->heavy_dump_period_ms); |
| 57 periodic_state_.heavy_dump_period_ms = min_time_between_dumps_ms; | 70 periodic_state_->heavy_dump_period_ms = min_time_between_dumps_ms; |
| 58 break; | 71 break; |
| 59 } | 72 } |
| 60 | 73 |
| 61 periodic_state_.min_timer_period_ms = std::min( | 74 periodic_state_->min_timer_period_ms = std::min( |
| 62 periodic_state_.min_timer_period_ms, min_time_between_dumps_ms); | 75 periodic_state_->min_timer_period_ms, min_time_between_dumps_ms); |
| 63 DCHECK_EQ(0u, periodic_state_.light_dump_period_ms % | 76 DCHECK_EQ(0u, periodic_state_->light_dump_period_ms % |
| 64 periodic_state_.min_timer_period_ms); | 77 periodic_state_->min_timer_period_ms); |
| 65 DCHECK_EQ(0u, periodic_state_.heavy_dump_period_ms % | 78 DCHECK_EQ(0u, periodic_state_->heavy_dump_period_ms % |
| 66 periodic_state_.min_timer_period_ms); | 79 periodic_state_->min_timer_period_ms); |
| 67 } | 80 } |
| 68 } | 81 } |
| 69 | 82 |
| 70 void MemoryDumpScheduler::NotifyPeriodicTriggerSupported() { | 83 void MemoryDumpScheduler::EnablePeriodicTriggerIfNeeded() { |
| 71 if (!periodic_state_.is_configured || periodic_state_.timer.IsRunning()) | 84 DCHECK(is_setup_); |
| 85 if (!periodic_state_->is_configured || periodic_state_->timer.IsRunning()) |
| 72 return; | 86 return; |
| 73 periodic_state_.light_dumps_rate = periodic_state_.light_dump_period_ms / | 87 periodic_state_->light_dumps_rate = periodic_state_->light_dump_period_ms / |
| 74 periodic_state_.min_timer_period_ms; | 88 periodic_state_->min_timer_period_ms; |
| 75 periodic_state_.heavy_dumps_rate = periodic_state_.heavy_dump_period_ms / | 89 periodic_state_->heavy_dumps_rate = periodic_state_->heavy_dump_period_ms / |
| 76 periodic_state_.min_timer_period_ms; | 90 periodic_state_->min_timer_period_ms; |
| 77 | 91 |
| 78 periodic_state_.dump_count = 0; | 92 periodic_state_->dump_count = 0; |
| 79 periodic_state_.timer.Start( | 93 periodic_state_->timer.Start( |
| 80 FROM_HERE, | 94 FROM_HERE, |
| 81 TimeDelta::FromMilliseconds(periodic_state_.min_timer_period_ms), | 95 TimeDelta::FromMilliseconds(periodic_state_->min_timer_period_ms), |
| 82 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); | 96 Bind(&MemoryDumpScheduler::RequestPeriodicGlobalDump, Unretained(this))); |
| 83 } | 97 } |
| 84 | 98 |
| 85 void MemoryDumpScheduler::NotifyPollingSupported() { | 99 void MemoryDumpScheduler::EnablePollingIfNeeded() { |
| 86 if (polling_state_.current_state != PollingTriggerState::CONFIGURED) | 100 DCHECK(is_setup_); |
| 101 if (polling_state_->current_state != PollingTriggerState::CONFIGURED) |
| 87 return; | 102 return; |
| 88 | 103 |
| 89 polling_state_.current_state = PollingTriggerState::ENABLED; | 104 polling_state_->current_state = PollingTriggerState::ENABLED; |
| 90 polling_state_.ResetTotals(); | 105 polling_state_->ResetTotals(); |
| 91 | 106 |
| 92 polling_state_.polling_task_runner->PostTask( | 107 polling_task_runner_->PostTask( |
| 93 FROM_HERE, | 108 FROM_HERE, |
| 94 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this))); | 109 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this))); |
| 95 } | 110 } |
| 96 | 111 |
| 97 void MemoryDumpScheduler::NotifyDumpTriggered() { | 112 void MemoryDumpScheduler::NotifyDumpTriggered() { |
| 98 if (polling_state_.polling_task_runner && | 113 if (polling_task_runner_ && |
| 99 !polling_state_.polling_task_runner->RunsTasksOnCurrentThread()) { | 114 !polling_task_runner_->RunsTasksOnCurrentThread()) { |
| 100 polling_state_.polling_task_runner->PostTask( | 115 polling_task_runner_->PostTask( |
| 101 FROM_HERE, | 116 FROM_HERE, |
| 102 Bind(&MemoryDumpScheduler::NotifyDumpTriggered, Unretained(this))); | 117 Bind(&MemoryDumpScheduler::NotifyDumpTriggered, Unretained(this))); |
| 103 return; | 118 return; |
| 104 } | 119 } |
| 105 if (polling_state_.current_state != PollingTriggerState::ENABLED) | 120 |
| 121 if (!polling_state_ || |
| 122 polling_state_->current_state != PollingTriggerState::ENABLED) { |
| 106 return; | 123 return; |
| 124 } |
| 107 | 125 |
| 108 polling_state_.ResetTotals(); | 126 polling_state_->ResetTotals(); |
| 109 } | 127 } |
| 110 | 128 |
| 111 void MemoryDumpScheduler::DisableAllTriggers() { | 129 void MemoryDumpScheduler::DisableAllTriggers() { |
| 112 if (periodic_state_.timer.IsRunning()) | 130 if (periodic_state_) { |
| 113 periodic_state_.timer.Stop(); | 131 if (periodic_state_->timer.IsRunning()) |
| 114 DisablePolling(); | 132 periodic_state_->timer.Stop(); |
| 133 periodic_state_.reset(); |
| 134 } |
| 135 |
| 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; |
| 115 } | 144 } |
| 116 | 145 |
| 117 void MemoryDumpScheduler::DisablePolling() { | 146 void MemoryDumpScheduler::DisablePollingOnPollingThread() { |
| 118 if (!polling_state_.polling_task_runner->RunsTasksOnCurrentThread()) { | 147 polling_state_->current_state = PollingTriggerState::DISABLED; |
| 119 if (polling_state_.polling_task_runner->PostTask( | 148 polling_state_.reset(); |
| 120 FROM_HERE, | |
| 121 Bind(&MemoryDumpScheduler::DisablePolling, Unretained(this)))) | |
| 122 return; | |
| 123 } | |
| 124 polling_state_.current_state = PollingTriggerState::DISABLED; | |
| 125 polling_state_.polling_task_runner = nullptr; | |
| 126 } | 149 } |
| 127 | 150 |
| 128 // static | 151 // static |
| 129 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { | 152 void MemoryDumpScheduler::SetPollingIntervalForTesting(uint32_t interval) { |
| 130 g_polling_interval_ms_for_testing = interval; | 153 g_polling_interval_ms_for_testing = interval; |
| 131 } | 154 } |
| 132 | 155 |
| 133 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { | 156 bool MemoryDumpScheduler::IsPeriodicTimerRunningForTesting() { |
| 134 return periodic_state_.timer.IsRunning(); | 157 return periodic_state_->timer.IsRunning(); |
| 135 } | 158 } |
| 136 | 159 |
| 137 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { | 160 void MemoryDumpScheduler::RequestPeriodicGlobalDump() { |
| 138 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; | 161 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; |
| 139 if (periodic_state_.light_dumps_rate > 0 && | 162 if (periodic_state_->light_dumps_rate > 0 && |
| 140 periodic_state_.dump_count % periodic_state_.light_dumps_rate == 0) | 163 periodic_state_->dump_count % periodic_state_->light_dumps_rate == 0) |
| 141 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | 164 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
| 142 if (periodic_state_.heavy_dumps_rate > 0 && | 165 if (periodic_state_->heavy_dumps_rate > 0 && |
| 143 periodic_state_.dump_count % periodic_state_.heavy_dumps_rate == 0) | 166 periodic_state_->dump_count % periodic_state_->heavy_dumps_rate == 0) |
| 144 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; | 167 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
| 145 ++periodic_state_.dump_count; | 168 ++periodic_state_->dump_count; |
| 146 | 169 |
| 147 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 170 mdm_->RequestGlobalDump(MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| 148 } | 171 } |
| 149 | 172 |
| 150 void MemoryDumpScheduler::PollMemoryOnPollingThread() { | 173 void MemoryDumpScheduler::PollMemoryOnPollingThread() { |
| 151 if (polling_state_.current_state != PollingTriggerState::ENABLED) | 174 if (polling_state_->current_state != PollingTriggerState::ENABLED) |
| 152 return; | 175 return; |
| 153 | 176 |
| 154 uint64_t polled_memory = 0; | 177 uint64_t polled_memory = 0; |
| 155 bool res = mdm_->PollFastMemoryTotal(&polled_memory); | 178 bool res = mdm_->PollFastMemoryTotal(&polled_memory); |
| 156 DCHECK(res); | 179 DCHECK(res); |
| 157 if (polling_state_.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { | 180 if (polling_state_->level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { |
| 158 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", | 181 TRACE_COUNTER1(MemoryDumpManager::kTraceCategory, "PolledMemoryMB", |
| 159 polled_memory / 1024 / 1024); | 182 polled_memory / 1024 / 1024); |
| 160 } | 183 } |
| 161 | 184 |
| 162 if (ShouldTriggerDump(polled_memory)) { | 185 if (ShouldTriggerDump(polled_memory)) { |
| 163 TRACE_EVENT_INSTANT1(MemoryDumpManager::kTraceCategory, | 186 TRACE_EVENT_INSTANT1(MemoryDumpManager::kTraceCategory, |
| 164 "Peak memory dump Triggered", | 187 "Peak memory dump Triggered", |
| 165 TRACE_EVENT_SCOPE_PROCESS, "total_usage_MB", | 188 TRACE_EVENT_SCOPE_PROCESS, "total_usage_MB", |
| 166 polled_memory / 1024 / 1024); | 189 polled_memory / 1024 / 1024); |
| 167 | 190 |
| 168 mdm_->RequestGlobalDump(MemoryDumpType::PEAK_MEMORY_USAGE, | 191 mdm_->RequestGlobalDump(MemoryDumpType::PEAK_MEMORY_USAGE, |
| 169 polling_state_.level_of_detail); | 192 polling_state_->level_of_detail); |
| 170 } | 193 } |
| 171 | 194 |
| 172 // TODO(ssid): Use RequestSchedulerCallback, crbug.com/607533. | 195 // TODO(ssid): Use RequestSchedulerCallback, crbug.com/607533. |
| 173 ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 196 ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 174 FROM_HERE, | 197 FROM_HERE, |
| 175 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this)), | 198 Bind(&MemoryDumpScheduler::PollMemoryOnPollingThread, Unretained(this)), |
| 176 TimeDelta::FromMilliseconds(polling_state_.polling_interval_ms)); | 199 TimeDelta::FromMilliseconds(polling_state_->polling_interval_ms)); |
| 177 } | 200 } |
| 178 | 201 |
| 179 bool MemoryDumpScheduler::ShouldTriggerDump(uint64_t current_memory_total) { | 202 bool MemoryDumpScheduler::ShouldTriggerDump(uint64_t current_memory_total) { |
| 180 // This function tries to detect peak memory usage as discussed in | 203 // This function tries to detect peak memory usage as discussed in |
| 181 // https://goo.gl/0kOU4A. | 204 // https://goo.gl/0kOU4A. |
| 182 | 205 |
| 183 if (current_memory_total == 0) | 206 if (current_memory_total == 0) |
| 184 return false; | 207 return false; |
| 185 | 208 |
| 186 bool should_dump = false; | 209 bool should_dump = false; |
| 187 ++polling_state_.num_polls_from_last_dump; | 210 ++polling_state_->num_polls_from_last_dump; |
| 188 if (polling_state_.last_dump_memory_total == 0) { | 211 if (polling_state_->last_dump_memory_total == 0) { |
| 189 // If it's first sample then trigger memory dump. | 212 // If it's first sample then trigger memory dump. |
| 190 should_dump = true; | 213 should_dump = true; |
| 191 } else if (polling_state_.min_polls_between_dumps > | 214 } else if (polling_state_->min_polls_between_dumps > |
| 192 polling_state_.num_polls_from_last_dump) { | 215 polling_state_->num_polls_from_last_dump) { |
| 193 return false; | 216 return false; |
| 194 } | 217 } |
| 195 | 218 |
| 196 int64_t increase_from_last_dump = | 219 int64_t increase_from_last_dump = |
| 197 current_memory_total - polling_state_.last_dump_memory_total; | 220 current_memory_total - polling_state_->last_dump_memory_total; |
| 198 should_dump |= | 221 should_dump |= |
| 199 increase_from_last_dump > polling_state_.memory_increase_threshold; | 222 increase_from_last_dump > polling_state_->memory_increase_threshold; |
| 200 should_dump |= IsCurrentSamplePeak(current_memory_total); | 223 should_dump |= IsCurrentSamplePeak(current_memory_total); |
| 201 if (should_dump) | 224 if (should_dump) |
| 202 polling_state_.ResetTotals(); | 225 polling_state_->ResetTotals(); |
| 203 return should_dump; | 226 return should_dump; |
| 204 } | 227 } |
| 205 | 228 |
| 206 bool MemoryDumpScheduler::IsCurrentSamplePeak( | 229 bool MemoryDumpScheduler::IsCurrentSamplePeak( |
| 207 uint64_t current_memory_total_bytes) { | 230 uint64_t current_memory_total_bytes) { |
| 208 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024; | 231 uint64_t current_memory_total_kb = current_memory_total_bytes / 1024; |
| 209 polling_state_.last_memory_totals_kb_index = | 232 polling_state_->last_memory_totals_kb_index = |
| 210 (polling_state_.last_memory_totals_kb_index + 1) % | 233 (polling_state_->last_memory_totals_kb_index + 1) % |
| 211 PollingTriggerState::kMaxNumMemorySamples; | 234 PollingTriggerState::kMaxNumMemorySamples; |
| 212 uint64_t mean = 0; | 235 uint64_t mean = 0; |
| 213 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i) { | 236 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i) { |
| 214 if (polling_state_.last_memory_totals_kb[i] == 0) { | 237 if (polling_state_->last_memory_totals_kb[i] == 0) { |
| 215 // Not enough samples to detect peaks. | 238 // Not enough samples to detect peaks. |
| 216 polling_state_ | 239 polling_state_ |
| 217 .last_memory_totals_kb[polling_state_.last_memory_totals_kb_index] = | 240 ->last_memory_totals_kb[polling_state_->last_memory_totals_kb_index] = |
| 218 current_memory_total_kb; | 241 current_memory_total_kb; |
| 219 return false; | 242 return false; |
| 220 } | 243 } |
| 221 mean += polling_state_.last_memory_totals_kb[i]; | 244 mean += polling_state_->last_memory_totals_kb[i]; |
| 222 } | 245 } |
| 223 mean = mean / PollingTriggerState::kMaxNumMemorySamples; | 246 mean = mean / PollingTriggerState::kMaxNumMemorySamples; |
| 224 uint64_t variance = 0; | 247 uint64_t variance = 0; |
| 225 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i) { | 248 for (uint32_t i = 0; i < PollingTriggerState::kMaxNumMemorySamples; ++i) { |
| 226 variance += (polling_state_.last_memory_totals_kb[i] - mean) * | 249 variance += (polling_state_->last_memory_totals_kb[i] - mean) * |
| 227 (polling_state_.last_memory_totals_kb[i] - mean); | 250 (polling_state_->last_memory_totals_kb[i] - mean); |
| 228 } | 251 } |
| 229 variance = variance / PollingTriggerState::kMaxNumMemorySamples; | 252 variance = variance / PollingTriggerState::kMaxNumMemorySamples; |
| 230 | 253 |
| 231 polling_state_ | 254 polling_state_ |
| 232 .last_memory_totals_kb[polling_state_.last_memory_totals_kb_index] = | 255 ->last_memory_totals_kb[polling_state_->last_memory_totals_kb_index] = |
| 233 current_memory_total_kb; | 256 current_memory_total_kb; |
| 234 | 257 |
| 235 // If stddev is less than 0.2% then we consider that the process is inactive. | 258 // If stddev is less than 0.2% then we consider that the process is inactive. |
| 236 bool is_stddev_low = variance < mean / 500 * mean / 500; | 259 bool is_stddev_low = variance < mean / 500 * mean / 500; |
| 237 if (is_stddev_low) | 260 if (is_stddev_low) |
| 238 return false; | 261 return false; |
| 239 | 262 |
| 240 // (mean + 3.69 * stddev) corresponds to a value that is higher than current | 263 // (mean + 3.69 * stddev) corresponds to a value that is higher than current |
| 241 // sample with 99.99% probability. | 264 // sample with 99.99% probability. |
| 242 return (current_memory_total_kb - mean) * (current_memory_total_kb - mean) > | 265 return (current_memory_total_kb - mean) * (current_memory_total_kb - mean) > |
| 243 (3.69 * 3.69 * variance); | 266 (3.69 * 3.69 * variance); |
| 244 } | 267 } |
| 245 | 268 |
| 246 MemoryDumpScheduler::PeriodicTriggerState::PeriodicTriggerState() | 269 MemoryDumpScheduler::PeriodicTriggerState::PeriodicTriggerState() |
| 247 : is_configured(false), | 270 : is_configured(false), |
| 248 dump_count(0), | 271 dump_count(0), |
| 249 min_timer_period_ms(std::numeric_limits<uint32_t>::max()), | 272 min_timer_period_ms(std::numeric_limits<uint32_t>::max()), |
| 250 light_dumps_rate(0), | 273 light_dumps_rate(0), |
| 251 heavy_dumps_rate(0), | 274 heavy_dumps_rate(0), |
| 252 light_dump_period_ms(0), | 275 light_dump_period_ms(0), |
| 253 heavy_dump_period_ms(0) {} | 276 heavy_dump_period_ms(0) {} |
| 254 | 277 |
| 255 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { | 278 MemoryDumpScheduler::PeriodicTriggerState::~PeriodicTriggerState() { |
| 256 DCHECK(!timer.IsRunning()); | 279 DCHECK(!timer.IsRunning()); |
| 257 } | 280 } |
| 258 | 281 |
| 259 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState( | 282 MemoryDumpScheduler::PollingTriggerState::PollingTriggerState() |
| 260 scoped_refptr<SingleThreadTaskRunner> polling_task_runner) | |
| 261 : current_state(DISABLED), | 283 : current_state(DISABLED), |
| 262 level_of_detail(MemoryDumpLevelOfDetail::FIRST), | 284 level_of_detail(MemoryDumpLevelOfDetail::FIRST), |
| 263 polling_task_runner(polling_task_runner), | |
| 264 polling_interval_ms(g_polling_interval_ms_for_testing | 285 polling_interval_ms(g_polling_interval_ms_for_testing |
| 265 ? g_polling_interval_ms_for_testing | 286 ? g_polling_interval_ms_for_testing |
| 266 : kMemoryTotalsPollingInterval), | 287 : kMemoryTotalsPollingInterval), |
| 267 min_polls_between_dumps(0), | 288 min_polls_between_dumps(0), |
| 268 num_polls_from_last_dump(-1), | 289 num_polls_from_last_dump(-1), |
| 269 last_dump_memory_total(0), | 290 last_dump_memory_total(0), |
| 270 memory_increase_threshold(0), | 291 memory_increase_threshold(0), |
| 271 last_memory_totals_kb_index(0) {} | 292 last_memory_totals_kb_index(0) {} |
| 272 | 293 |
| 273 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() { | 294 MemoryDumpScheduler::PollingTriggerState::~PollingTriggerState() {} |
| 274 DCHECK(!polling_task_runner); | |
| 275 } | |
| 276 | 295 |
| 277 void MemoryDumpScheduler::PollingTriggerState::ResetTotals() { | 296 void MemoryDumpScheduler::PollingTriggerState::ResetTotals() { |
| 278 if (!memory_increase_threshold) { | 297 if (!memory_increase_threshold) { |
| 279 memory_increase_threshold = kDefaultMemoryIncreaseThreshold; | 298 memory_increase_threshold = kDefaultMemoryIncreaseThreshold; |
| 280 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ | 299 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ |
| 281 defined(OS_ANDROID) | 300 defined(OS_ANDROID) |
| 282 // Set threshold to 1% of total system memory. | 301 // Set threshold to 1% of total system memory. |
| 283 SystemMemoryInfoKB meminfo; | 302 SystemMemoryInfoKB meminfo; |
| 284 bool res = GetSystemMemoryInfo(&meminfo); | 303 bool res = GetSystemMemoryInfo(&meminfo); |
| 285 if (res) { | 304 if (res) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 298 last_memory_totals_kb[last_memory_totals_kb_index] * 1024; | 317 last_memory_totals_kb[last_memory_totals_kb_index] * 1024; |
| 299 } | 318 } |
| 300 num_polls_from_last_dump = 0; | 319 num_polls_from_last_dump = 0; |
| 301 for (uint32_t i = 0; i < kMaxNumMemorySamples; ++i) | 320 for (uint32_t i = 0; i < kMaxNumMemorySamples; ++i) |
| 302 last_memory_totals_kb[i] = 0; | 321 last_memory_totals_kb[i] = 0; |
| 303 last_memory_totals_kb_index = 0; | 322 last_memory_totals_kb_index = 0; |
| 304 } | 323 } |
| 305 | 324 |
| 306 } // namespace trace_event | 325 } // namespace trace_event |
| 307 } // namespace base | 326 } // namespace base |
| OLD | NEW |