| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chrome/browser/chromeos/resource_reporter/resource_reporter.h" | 5 #include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 #include <queue> | 8 #include <queue> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/memory/memory_coordinator_client_registry.h" |
| 12 #include "base/memory/memory_pressure_monitor.h" | 13 #include "base/memory/memory_pressure_monitor.h" |
| 13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/rand_util.h" | 15 #include "base/rand_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/sys_info.h" | 17 #include "base/sys_info.h" |
| 17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 18 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/task_manager/task_manager_interface.h" | 20 #include "chrome/browser/task_manager/task_manager_interface.h" |
| 20 #include "components/rappor/rappor_service.h" | 21 #include "components/rappor/rappor_service.h" |
| 21 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 113 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 113 | 114 |
| 114 if (is_monitoring_) | 115 if (is_monitoring_) |
| 115 return; | 116 return; |
| 116 | 117 |
| 117 task_manager_to_observe_ = task_manager_to_observe; | 118 task_manager_to_observe_ = task_manager_to_observe; |
| 118 DCHECK(task_manager_to_observe_); | 119 DCHECK(task_manager_to_observe_); |
| 119 is_monitoring_ = true; | 120 is_monitoring_ = true; |
| 120 memory_pressure_listener_.reset(new base::MemoryPressureListener( | 121 memory_pressure_listener_.reset(new base::MemoryPressureListener( |
| 121 base::Bind(&ResourceReporter::OnMemoryPressure, base::Unretained(this)))); | 122 base::Bind(&ResourceReporter::OnMemoryPressure, base::Unretained(this)))); |
| 123 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); |
| 122 } | 124 } |
| 123 | 125 |
| 124 void ResourceReporter::StopMonitoring() { | 126 void ResourceReporter::StopMonitoring() { |
| 125 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 127 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 126 | 128 |
| 127 if (!is_monitoring_) | 129 if (!is_monitoring_) |
| 128 return; | 130 return; |
| 129 | 131 |
| 130 // We might be shutting down right after a critical memory pressure event, and | 132 // We might be shutting down right after a critical memory pressure event, and |
| 131 // before we get an update from the task manager with all background | 133 // before we get an update from the task manager with all background |
| 132 // calculations refreshed. In this case we must unregister from the task | 134 // calculations refreshed. In this case we must unregister from the task |
| 133 // manager here. | 135 // manager here. |
| 134 if (observed_task_manager()) | 136 StopRecordingCurrentState(); |
| 135 observed_task_manager()->RemoveObserver(this); | |
| 136 | 137 |
| 137 is_monitoring_ = false; | 138 is_monitoring_ = false; |
| 138 memory_pressure_listener_.reset(); | 139 memory_pressure_listener_.reset(); |
| 140 |
| 141 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this); |
| 139 } | 142 } |
| 140 | 143 |
| 141 void ResourceReporter::OnTasksRefreshedWithBackgroundCalculations( | 144 void ResourceReporter::OnTasksRefreshedWithBackgroundCalculations( |
| 142 const task_manager::TaskIdList& task_ids) { | 145 const task_manager::TaskIdList& task_ids) { |
| 143 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 144 | 147 |
| 145 task_records_.clear(); | 148 task_records_.clear(); |
| 146 task_records_.reserve(task_ids.size()); | 149 task_records_.reserve(task_ids.size()); |
| 147 | 150 |
| 148 for (const auto& id : task_ids) { | 151 for (const auto& id : task_ids) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 187 } |
| 185 | 188 |
| 186 // Now that we got the data, we don't need the task manager anymore. | 189 // Now that we got the data, we don't need the task manager anymore. |
| 187 if (base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel() != | 190 if (base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel() != |
| 188 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL || | 191 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL || |
| 189 !task_records_.empty()) { | 192 !task_records_.empty()) { |
| 190 // The memory pressure events are emitted once per second. In order to avoid | 193 // The memory pressure events are emitted once per second. In order to avoid |
| 191 // unsubscribing and then resubscribing to the task manager again on the | 194 // unsubscribing and then resubscribing to the task manager again on the |
| 192 // next event, we keep listening to the task manager as long as the memory | 195 // next event, we keep listening to the task manager as long as the memory |
| 193 // pressure level is critical AND we couldn't find any violators yet. | 196 // pressure level is critical AND we couldn't find any violators yet. |
| 194 observed_task_manager()->RemoveObserver(this); | 197 StopRecordingCurrentState(); |
| 195 } | 198 } |
| 196 | 199 |
| 197 // Schedule reporting the samples. | 200 // Schedule reporting the samples. |
| 198 base::ThreadTaskRunnerHandle::Get()->PostTask( | 201 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 199 FROM_HERE, | 202 FROM_HERE, |
| 200 base::Bind(&ResourceReporter::ReportSamples, base::Unretained(this))); | 203 base::Bind(&ResourceReporter::ReportSamples, base::Unretained(this))); |
| 201 } | 204 } |
| 202 | 205 |
| 203 // static | 206 // static |
| 204 const double ResourceReporter::kTaskCpuThresholdForReporting = 70.0; | 207 const double ResourceReporter::kTaskCpuThresholdForReporting = 70.0; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES)); | 387 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES)); |
| 385 rappor_service->RecordSampleObj(kMemoryRapporMetric, | 388 rappor_service->RecordSampleObj(kMemoryRapporMetric, |
| 386 std::move(memory_sample)); | 389 std::move(memory_sample)); |
| 387 } | 390 } |
| 388 } | 391 } |
| 389 | 392 |
| 390 void ResourceReporter::OnMemoryPressure( | 393 void ResourceReporter::OnMemoryPressure( |
| 391 MemoryPressureLevel memory_pressure_level) { | 394 MemoryPressureLevel memory_pressure_level) { |
| 392 if (memory_pressure_level == | 395 if (memory_pressure_level == |
| 393 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) { | 396 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) { |
| 394 // If we are already listening to the task manager, then we're waiting for | 397 StartRecordingCurrentState(); |
| 395 // a refresh event. | |
| 396 if (observed_task_manager()) | |
| 397 return; | |
| 398 | |
| 399 // We only record Rappor samples only if it's the first ever critical memory | |
| 400 // pressure event we receive, or it has been more than | |
| 401 // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples. | |
| 402 if (g_browser_process->local_state()) { | |
| 403 const base::Time now = base::Time::NowFromSystemTime(); | |
| 404 const base::Time last_rappor_report_time = | |
| 405 base::Time::FromDoubleT(g_browser_process->local_state()->GetDouble( | |
| 406 kLastRapporReportTimeKey)); | |
| 407 const base::TimeDelta delta_since_last_report = | |
| 408 now >= last_rappor_report_time ? now - last_rappor_report_time | |
| 409 : base::TimeDelta::Max(); | |
| 410 | |
| 411 if (delta_since_last_report < kMinimumTimeBetweenReports) | |
| 412 return; | |
| 413 } | |
| 414 | |
| 415 // Start listening to the task manager and wait for the first refresh event | |
| 416 // with background calculations completion. | |
| 417 task_manager_to_observe_->AddObserver(this); | |
| 418 } else { | 398 } else { |
| 419 // If we are still listening to the task manager from an earlier critical | 399 StopRecordingCurrentState(); |
| 420 // memory pressure level, we need to stop listening to it. | |
| 421 if (observed_task_manager()) | |
| 422 observed_task_manager()->RemoveObserver(this); | |
| 423 } | 400 } |
| 424 } | 401 } |
| 425 | 402 |
| 403 void ResourceReporter::StartRecordingCurrentState() { |
| 404 // If we are already listening to the task manager, then we're waiting for |
| 405 // a refresh event. |
| 406 if (observed_task_manager()) |
| 407 return; |
| 408 |
| 409 // We only record Rappor samples only if it's the first ever critical memory |
| 410 // pressure event we receive, or it has been more than |
| 411 // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples. |
| 412 if (g_browser_process->local_state()) { |
| 413 const base::Time now = base::Time::NowFromSystemTime(); |
| 414 const base::Time last_rappor_report_time = base::Time::FromDoubleT( |
| 415 g_browser_process->local_state()->GetDouble(kLastRapporReportTimeKey)); |
| 416 const base::TimeDelta delta_since_last_report = |
| 417 now >= last_rappor_report_time ? now - last_rappor_report_time |
| 418 : base::TimeDelta::Max(); |
| 419 |
| 420 if (delta_since_last_report < kMinimumTimeBetweenReports) |
| 421 return; |
| 422 } |
| 423 |
| 424 // Start listening to the task manager and wait for the first refresh event |
| 425 // with background calculations completion. |
| 426 task_manager_to_observe_->AddObserver(this); |
| 427 } |
| 428 |
| 429 void ResourceReporter::StopRecordingCurrentState() { |
| 430 // If we are still listening to the task manager from an earlier critical |
| 431 // memory pressure level, we need to stop listening to it. |
| 432 if (observed_task_manager()) |
| 433 observed_task_manager()->RemoveObserver(this); |
| 434 } |
| 435 |
| 436 void ResourceReporter::OnMemoryStateChange(base::MemoryState state) { |
| 437 switch (state) { |
| 438 case base::MemoryState::NORMAL: |
| 439 StopRecordingCurrentState(); |
| 440 break; |
| 441 case base::MemoryState::THROTTLED: |
| 442 StartRecordingCurrentState(); |
| 443 break; |
| 444 case base::MemoryState::SUSPENDED: |
| 445 // Note: Not supported at present. Fall through. |
| 446 case base::MemoryState::UNKNOWN: |
| 447 NOTREACHED(); |
| 448 break; |
| 449 } |
| 450 } |
| 451 |
| 426 } // namespace chromeos | 452 } // namespace chromeos |
| OLD | NEW |