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

Side by Side Diff: chrome/browser/chromeos/resource_reporter/resource_reporter.cc

Issue 2363223002: Fix the Chrome OS ResourceReporter (Closed)
Patch Set: Fix 2 browser_tests Created 4 years, 2 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 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/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/rand_util.h" 13 #include "base/rand_util.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/sys_info.h" 15 #include "base/sys_info.h"
16 #include "base/time/time.h"
16 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/task_manager/task_manager_interface.h" 18 #include "chrome/browser/task_manager/task_manager_interface.h"
18 #include "components/rappor/rappor_service.h" 19 #include "components/rappor/rappor_service.h"
19 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
20 21
21 namespace chromeos { 22 namespace chromeos {
22 23
23 namespace { 24 namespace {
24 25
25 #define GET_ENUM_VAL(enum_entry) static_cast<int>(enum_entry) 26 #define GET_ENUM_VAL(enum_entry) static_cast<int>(enum_entry)
26 27
27 // The task manager refresh interval, currently at 1 minute. 28 // At a critical memory pressure event, we only care about a single complete
28 const int64_t kRefreshIntervalSeconds = 60; 29 // refresh from the task manager (with background calculations). So we request
30 // the minimum refresh rate (once per second).
31 constexpr int64_t kRefreshIntervalSeconds = 1;
29 32
30 // Various memory usage sizes in bytes. 33 // Various memory usage sizes in bytes.
31 const int64_t kMemory1GB = 1024 * 1024 * 1024; 34 constexpr int64_t kMemory1GB = 1024 * 1024 * 1024;
32 const int64_t kMemory800MB = 800 * 1024 * 1024; 35 constexpr int64_t kMemory800MB = 800 * 1024 * 1024;
33 const int64_t kMemory600MB = 600 * 1024 * 1024; 36 constexpr int64_t kMemory600MB = 600 * 1024 * 1024;
34 const int64_t kMemory400MB = 400 * 1024 * 1024; 37 constexpr int64_t kMemory400MB = 400 * 1024 * 1024;
35 const int64_t kMemory200MB = 200 * 1024 * 1024; 38 constexpr int64_t kMemory200MB = 200 * 1024 * 1024;
36 39
37 // The name of the Rappor metric to report the CPU usage. 40 // The name of the Rappor metric to report the CPU usage.
38 const char kCpuRapporMetric[] = "ResourceReporter.Cpu"; 41 constexpr char kCpuRapporMetric[] = "ResourceReporter.Cpu";
39 42
40 // The name of the Rappor metric to report the memory usage. 43 // The name of the Rappor metric to report the memory usage.
41 const char kMemoryRapporMetric[] = "ResourceReporter.Memory"; 44 constexpr char kMemoryRapporMetric[] = "ResourceReporter.Memory";
42 45
43 // The name of the string field of the Rappor metrics in which we'll record the 46 // The name of the string field of the Rappor metrics in which we'll record the
44 // task's Rappor sample name. 47 // task's Rappor sample name.
45 const char kRapporTaskStringField[] = "task"; 48 constexpr char kRapporTaskStringField[] = "task";
46 49
47 // The name of the flags field of the Rappor metrics in which we'll store the 50 // The name of the flags field of the Rappor metrics in which we'll store the
48 // priority of the process on which the task is running. 51 // priority of the process on which the task is running.
49 const char kRapporPriorityFlagsField[] = "priority"; 52 constexpr char kRapporPriorityFlagsField[] = "priority";
50 53
51 // The name of the flags field of the CPU usage Rappor metrics in which we'll 54 // The name of the flags field of the CPU usage Rappor metrics in which we'll
52 // record the number of cores in the current system. 55 // record the number of cores in the current system.
53 const char kRapporNumCoresRangeFlagsField[] = "num_cores_range"; 56 constexpr char kRapporNumCoresRangeFlagsField[] = "num_cores_range";
54 57
55 // The name of the flags field of the Rappor metrics in which we'll store the 58 // The name of the flags field of the Rappor metrics in which we'll store the
56 // CPU / memory usage ranges. 59 // CPU / memory usage ranges.
57 const char kRapporUsageRangeFlagsField[] = "usage_range"; 60 constexpr char kRapporUsageRangeFlagsField[] = "usage_range";
58 61
59 // Currently set to be one day. 62 // Key used to store the last time a Rappor report was recorded in local_state.
60 const int kMinimumTimeBetweenReportsInMs = 1 * 24 * 60 * 60 * 1000; 63 constexpr char kLastRapporReportTimeKey[] =
64 "resource_reporter.last_report_time";
61 65
62 // A functor to sort the TaskRecords by their |cpu|. 66 // To keep privacy guarantees of Rappor, we limit the reports to at most once
63 struct TaskRecordCpuLessThan { 67 // per day.
64 bool operator()(ResourceReporter::TaskRecord* const& lhs, 68 constexpr base::TimeDelta kMinimumTimeBetweenReports =
ncarter (slow) 2016/09/29 21:32:11 constexpr + TimeDelta is an amazing combo.
afakhry 2016/10/04 18:28:58 Absolutely!
65 ResourceReporter::TaskRecord* const& rhs) const { 69 base::TimeDelta::FromDays(1);
66 if (lhs->cpu_percent == rhs->cpu_percent)
67 return lhs->id < rhs->id;
68 return lhs->cpu_percent < rhs->cpu_percent;
69 }
70 };
71
72 // A functor to sort the TaskRecords by their |memory|.
73 struct TaskRecordMemoryLessThan {
74 bool operator()(ResourceReporter::TaskRecord* const& lhs,
75 ResourceReporter::TaskRecord* const& rhs) const {
76 if (lhs->memory_bytes == rhs->memory_bytes)
77 return lhs->id < rhs->id;
78 return lhs->memory_bytes < rhs->memory_bytes;
79 }
80 };
81 70
82 } // namespace 71 } // namespace
83 72
84 ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId task_id) 73 ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId task_id)
85 : id(task_id), cpu_percent(0.0), memory_bytes(0), is_background(false) {} 74 : id(task_id), cpu_percent(0.0), memory_bytes(0), is_background(false) {}
86 75
87 ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId the_id, 76 ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId the_id,
88 const std::string& task_name, 77 const std::string& task_name,
89 double cpu_percent, 78 double cpu_percent,
90 int64_t memory_bytes, 79 int64_t memory_bytes,
91 bool background) 80 bool background)
92 : id(the_id), 81 : id(the_id),
93 task_name_for_rappor(task_name), 82 task_name_for_rappor(task_name),
94 cpu_percent(cpu_percent), 83 cpu_percent(cpu_percent),
95 memory_bytes(memory_bytes), 84 memory_bytes(memory_bytes),
96 is_background(background) {} 85 is_background(background) {}
97 86
98 ResourceReporter::~ResourceReporter() { 87 ResourceReporter::~ResourceReporter() {
99 } 88 }
100 89
101 // static 90 // static
102 ResourceReporter* ResourceReporter::GetInstance() { 91 ResourceReporter* ResourceReporter::GetInstance() {
103 return base::Singleton<ResourceReporter>::get(); 92 return base::Singleton<ResourceReporter>::get();
104 } 93 }
105 94
95 // static
96 void ResourceReporter::RegisterPrefs(PrefRegistrySimple* registry) {
97 registry->RegisterDoublePref(kLastRapporReportTimeKey, 0.0);
98 }
99
106 void ResourceReporter::StartMonitoring() { 100 void ResourceReporter::StartMonitoring() {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 101 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
108 102
109 if (is_monitoring_) 103 if (is_monitoring_)
110 return; 104 return;
111 105
112 is_monitoring_ = true; 106 is_monitoring_ = true;
113 task_manager::TaskManagerInterface::GetTaskManager()->AddObserver(this);
114 memory_pressure_listener_.reset(new base::MemoryPressureListener( 107 memory_pressure_listener_.reset(new base::MemoryPressureListener(
115 base::Bind(&ResourceReporter::OnMemoryPressure, base::Unretained(this)))); 108 base::Bind(&ResourceReporter::OnMemoryPressure, base::Unretained(this))));
116 } 109 }
117 110
118 void ResourceReporter::StopMonitoring() { 111 void ResourceReporter::StopMonitoring() {
119 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
120 113
121 if (!is_monitoring_) 114 if (!is_monitoring_)
122 return; 115 return;
123 116
117 // We might be shutting down right after a critical memory pressure event, and
118 // before we get an update from the task manager with all background
119 // calculations refreshed. In this case we must unregister from the task
120 // manager here.
121 if (observed_task_manager())
122 observed_task_manager()->RemoveObserver(this);
123
124 is_monitoring_ = false; 124 is_monitoring_ = false;
125 memory_pressure_listener_.reset(); 125 memory_pressure_listener_.reset();
126 task_manager::TaskManagerInterface::GetTaskManager()->RemoveObserver(this);
127 } 126 }
128 127
129 void ResourceReporter::OnTaskAdded(task_manager::TaskId id) { 128 void ResourceReporter::OnTasksRefreshedWithBackgroundCalculations(
130 // Ignore this event. 129 const task_manager::TaskIdList& task_ids) {
131 } 130 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
132 131
133 void ResourceReporter::OnTaskToBeRemoved(task_manager::TaskId id) { 132 task_records_.clear();
134 auto it = task_records_.find(id); 133 task_records_.reserve(task_ids.size());
135 if (it == task_records_.end())
136 return;
137
138 // Must be erased from the sorted set first.
139 // Note: this could mean that the sorted records are now less than
140 // |kTopConsumerCount| with other records in |task_records_| that can be
141 // added now. That's ok, we ignore this case.
142 auto cpu_it = std::find(task_records_by_cpu_.begin(),
143 task_records_by_cpu_.end(),
144 it->second.get());
145 if (cpu_it != task_records_by_cpu_.end())
146 task_records_by_cpu_.erase(cpu_it);
147
148 auto memory_it = std::find(task_records_by_memory_.begin(),
149 task_records_by_memory_.end(),
150 it->second.get());
151 if (memory_it != task_records_by_memory_.end())
152 task_records_by_memory_.erase(memory_it);
153
154 task_records_.erase(it);
155 }
156
157 void ResourceReporter::OnTasksRefreshed(
158 const task_manager::TaskIdList& task_ids) {
159 have_seen_first_task_manager_refresh_ = true;
160
161 // A priority queue to sort the task records by their |cpu|. Greatest |cpu|
162 // first.
163 std::priority_queue<TaskRecord*,
164 std::vector<TaskRecord*>,
165 TaskRecordCpuLessThan> records_by_cpu_queue;
166 // A priority queue to sort the task records by their |memory|. Greatest
167 // |memory| first.
168 std::priority_queue<TaskRecord*,
169 std::vector<TaskRecord*>,
170 TaskRecordMemoryLessThan> records_by_memory_queue;
171 task_records_by_cpu_.clear();
172 task_records_by_cpu_.reserve(kTopConsumersCount);
173 task_records_by_memory_.clear();
174 task_records_by_memory_.reserve(kTopConsumersCount);
175 134
176 for (const auto& id : task_ids) { 135 for (const auto& id : task_ids) {
177 const double cpu_usage = observed_task_manager()->GetCpuUsage(id); 136 const double cpu_usage = observed_task_manager()->GetCpuUsage(id);
178 const int64_t memory_usage = 137 const int64_t memory_usage =
179 observed_task_manager()->GetPhysicalMemoryUsage(id); 138 observed_task_manager()->GetPhysicalMemoryUsage(id);
180 139
181 // Browser and GPU processes are reported later using UMA histograms as they 140 // Browser and GPU processes are reported later using UMA histograms as they
182 // don't have any privacy issues. 141 // don't have any privacy issues.
183 const auto task_type = observed_task_manager()->GetType(id); 142 const auto task_type = observed_task_manager()->GetType(id);
184 switch (task_type) { 143 switch (task_type) {
185 case task_manager::Task::UNKNOWN: 144 case task_manager::Task::UNKNOWN:
186 case task_manager::Task::ZYGOTE: 145 case task_manager::Task::ZYGOTE:
187 break; 146 break;
188 147
189 case task_manager::Task::BROWSER: 148 case task_manager::Task::BROWSER:
190 last_browser_process_cpu_ = cpu_usage; 149 last_browser_process_cpu_ = cpu_usage;
191 last_browser_process_memory_ = memory_usage >= 0 ? memory_usage : 0; 150 last_browser_process_memory_ = memory_usage >= 0 ? memory_usage : 0;
192 break; 151 break;
193 152
194 case task_manager::Task::GPU: 153 case task_manager::Task::GPU:
195 last_gpu_process_cpu_ = cpu_usage; 154 last_gpu_process_cpu_ = cpu_usage;
196 last_gpu_process_memory_ = memory_usage >= 0 ? memory_usage : 0; 155 last_gpu_process_memory_ = memory_usage >= 0 ? memory_usage : 0;
197 break; 156 break;
198 157
199 default: 158 default:
200 // Other tasks types will be reported using Rappor. 159 // Other tasks types will be reported using Rappor.
201 TaskRecord* task_data = nullptr; 160 if (memory_usage < kTaskMemoryThresholdForReporting &&
202 auto itr = task_records_.find(id); 161 cpu_usage < kTaskCpuThresholdForReporting) {
203 if (itr == task_records_.end()) { 162 // We only care about CPU and memory intensive tasks.
204 task_data = new TaskRecord(id); 163 break;
205 task_records_[id] = base::WrapUnique(task_data);
206 } else {
207 task_data = itr->second.get();
208 } 164 }
209 165
210 DCHECK_EQ(task_data->id, id); 166 task_records_.emplace_back(
211 task_data->task_name_for_rappor = 167 id, observed_task_manager()->GetTaskNameForRappor(id), cpu_usage,
212 observed_task_manager()->GetTaskNameForRappor(id); 168 memory_usage,
213 task_data->cpu_percent = cpu_usage; 169 observed_task_manager()->IsTaskOnBackgroundedProcess(id));
214 task_data->memory_bytes = memory_usage;
215 task_data->is_background =
216 observed_task_manager()->IsTaskOnBackgroundedProcess(id);
217
218 // Push only valid or useful data to both priority queues. They might
219 // end up having more records than |kTopConsumerCount|, that's fine.
220 // We'll take care of that next.
221 if (task_data->cpu_percent > 0)
222 records_by_cpu_queue.push(task_data);
223 if (task_data->memory_bytes > 0)
224 records_by_memory_queue.push(task_data);
225 } 170 }
226 } 171 }
227 172
228 // Sort the |kTopConsumersCount| task records by their CPU and memory usage. 173 // Now that we got the data, we don't need the task manager anymore.
229 while (!records_by_cpu_queue.empty() && 174 observed_task_manager()->RemoveObserver(this);
230 task_records_by_cpu_.size() < kTopConsumersCount) {
231 task_records_by_cpu_.push_back(records_by_cpu_queue.top());
232 records_by_cpu_queue.pop();
233 }
234 175
235 while (!records_by_memory_queue.empty() && 176 // Schedule reporting the samples.
236 task_records_by_memory_.size() < kTopConsumersCount) { 177 base::ThreadTaskRunnerHandle::Get()->PostTask(
237 task_records_by_memory_.push_back(records_by_memory_queue.top()); 178 FROM_HERE,
238 records_by_memory_queue.pop(); 179 base::Bind(&ResourceReporter::ReportSamples, base::Unretained(this)));
239 }
240 } 180 }
241 181
242 // static 182 // static
243 const size_t ResourceReporter::kTopConsumersCount = 10U; 183 const double ResourceReporter::kTaskCpuThresholdForReporting = 70.0;
184
185 // static
186 const int64_t ResourceReporter::kTaskMemoryThresholdForReporting =
187 800 * 1024 * 1024;
244 188
245 ResourceReporter::ResourceReporter() 189 ResourceReporter::ResourceReporter()
246 : TaskManagerObserver(base::TimeDelta::FromSeconds(kRefreshIntervalSeconds), 190 : TaskManagerObserver(base::TimeDelta::FromSeconds(kRefreshIntervalSeconds),
247 task_manager::REFRESH_TYPE_CPU | 191 task_manager::REFRESH_TYPE_CPU |
248 task_manager::REFRESH_TYPE_MEMORY | 192 task_manager::REFRESH_TYPE_MEMORY |
249 task_manager::REFRESH_TYPE_PRIORITY), 193 task_manager::REFRESH_TYPE_PRIORITY),
250 system_cpu_cores_range_(GetCurrentSystemCpuCoresRange()) {} 194 system_cpu_cores_range_(GetCurrentSystemCpuCoresRange()),
195 last_browser_process_cpu_(0.0),
196 last_gpu_process_cpu_(0.0),
197 last_browser_process_memory_(0),
198 last_gpu_process_memory_(0),
199 is_monitoring_(false) {}
251 200
252 // static 201 // static
253 std::unique_ptr<rappor::Sample> ResourceReporter::CreateRapporSample( 202 std::unique_ptr<rappor::Sample> ResourceReporter::CreateRapporSample(
254 rappor::RapporService* rappor_service, 203 rappor::RapporService* rappor_service,
255 const ResourceReporter::TaskRecord& task_record) { 204 const ResourceReporter::TaskRecord& task_record) {
256 std::unique_ptr<rappor::Sample> sample( 205 std::unique_ptr<rappor::Sample> sample(
257 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE)); 206 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE));
258 sample->SetStringField(kRapporTaskStringField, 207 sample->SetStringField(kRapporTaskStringField,
259 task_record.task_name_for_rappor); 208 task_record.task_name_for_rappor);
260 sample->SetFlagsField(kRapporPriorityFlagsField, 209 sample->SetFlagsField(kRapporPriorityFlagsField,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 264
316 NOTREACHED(); 265 NOTREACHED();
317 return CpuCoresNumberRange::RANGE_NA; 266 return CpuCoresNumberRange::RANGE_NA;
318 } 267 }
319 268
320 const ResourceReporter::TaskRecord* ResourceReporter::SampleTaskByCpu() const { 269 const ResourceReporter::TaskRecord* ResourceReporter::SampleTaskByCpu() const {
321 // Perform a weighted random sampling taking the tasks' CPU usage as their 270 // Perform a weighted random sampling taking the tasks' CPU usage as their
322 // weights to randomly select one of them to be reported by Rappor. The higher 271 // weights to randomly select one of them to be reported by Rappor. The higher
323 // the CPU usage, the higher the chance that the task will be selected. 272 // the CPU usage, the higher the chance that the task will be selected.
324 // See https://en.wikipedia.org/wiki/Reservoir_sampling. 273 // See https://en.wikipedia.org/wiki/Reservoir_sampling.
325 TaskRecord* sampled_task = nullptr; 274 const TaskRecord* sampled_task = nullptr;
326 double cpu_weights_sum = 0; 275 double cpu_weights_sum = 0;
327 for (auto* task_data : task_records_by_cpu_) { 276 for (const auto& task_data : task_records_) {
328 if ((base::RandDouble() * (cpu_weights_sum + task_data->cpu_percent)) >= 277 if ((base::RandDouble() * (cpu_weights_sum + task_data.cpu_percent)) >=
329 cpu_weights_sum) { 278 cpu_weights_sum) {
330 sampled_task = task_data; 279 sampled_task = &task_data;
331 } 280 }
332 cpu_weights_sum += task_data->cpu_percent; 281 cpu_weights_sum += task_data.cpu_percent;
333 } 282 }
334 283
335 return sampled_task; 284 return sampled_task;
336 } 285 }
337 286
338 const ResourceReporter::TaskRecord* 287 const ResourceReporter::TaskRecord*
339 ResourceReporter::SampleTaskByMemory() const { 288 ResourceReporter::SampleTaskByMemory() const {
340 // Perform a weighted random sampling taking the tasks' memory usage as their 289 // Perform a weighted random sampling taking the tasks' memory usage as their
341 // weights to randomly select one of them to be reported by Rappor. The higher 290 // weights to randomly select one of them to be reported by Rappor. The higher
342 // the memory usage, the higher the chance that the task will be selected. 291 // the memory usage, the higher the chance that the task will be selected.
343 // See https://en.wikipedia.org/wiki/Reservoir_sampling. 292 // See https://en.wikipedia.org/wiki/Reservoir_sampling.
344 TaskRecord* sampled_task = nullptr; 293 const TaskRecord* sampled_task = nullptr;
345 int64_t memory_weights_sum = 0; 294 int64_t memory_weights_sum = 0;
346 for (auto* task_data : task_records_by_memory_) { 295 for (const auto& task_data : task_records_) {
347 if ((base::RandDouble() * (memory_weights_sum + task_data->memory_bytes)) >= 296 if ((base::RandDouble() * (memory_weights_sum + task_data.memory_bytes)) >=
348 memory_weights_sum) { 297 memory_weights_sum) {
349 sampled_task = task_data; 298 sampled_task = &task_data;
350 } 299 }
351 memory_weights_sum += task_data->memory_bytes; 300 memory_weights_sum += task_data.memory_bytes;
352 } 301 }
353 302
354 return sampled_task; 303 return sampled_task;
355 } 304 }
356 305
306 void ResourceReporter::ReportSamples() {
307 // Report browser and GPU processes usage using UMA histograms.
308 UMA_HISTOGRAM_ENUMERATION(
309 "ResourceReporter.BrowserProcess.CpuUsage",
310 GET_ENUM_VAL(GetCpuUsageRange(last_browser_process_cpu_)),
311 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
312 UMA_HISTOGRAM_ENUMERATION(
313 "ResourceReporter.BrowserProcess.MemoryUsage",
314 GET_ENUM_VAL(GetMemoryUsageRange(last_browser_process_memory_)),
315 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
316 UMA_HISTOGRAM_ENUMERATION(
317 "ResourceReporter.GpuProcess.CpuUsage",
318 GET_ENUM_VAL(GetCpuUsageRange(last_gpu_process_cpu_)),
319 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
320 UMA_HISTOGRAM_ENUMERATION(
321 "ResourceReporter.GpuProcess.MemoryUsage",
322 GET_ENUM_VAL(GetMemoryUsageRange(last_gpu_process_memory_)),
323 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
324
325 // For the rest of tasks, report them using Rappor.
326 auto* rappor_service = g_browser_process->rappor_service();
327 if (!rappor_service || task_records_.empty())
328 return;
329
330 // We have samples to report via Rappor. Store 'now' as the time of the last
331 // report.
332 if (g_browser_process->local_state()) {
333 g_browser_process->local_state()->SetDouble(
334 kLastRapporReportTimeKey, base::Time::NowFromSystemTime().ToDoubleT());
335 }
336
337 // Use weighted random sampling to select a task to report in the CPU
338 // metric.
339 const TaskRecord* sampled_cpu_task = SampleTaskByCpu();
340 if (sampled_cpu_task) {
341 std::unique_ptr<rappor::Sample> cpu_sample(
342 CreateRapporSample(rappor_service, *sampled_cpu_task));
343 cpu_sample->SetFlagsField(kRapporNumCoresRangeFlagsField,
344 GET_ENUM_VAL(system_cpu_cores_range_),
345 GET_ENUM_VAL(CpuCoresNumberRange::NUM_RANGES));
346 cpu_sample->SetFlagsField(
347 kRapporUsageRangeFlagsField,
348 GET_ENUM_VAL(GetCpuUsageRange(sampled_cpu_task->cpu_percent)),
349 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
350 rappor_service->RecordSampleObj(kCpuRapporMetric, std::move(cpu_sample));
351 }
352
353 // Use weighted random sampling to select a task to report in the memory
354 // metric.
355 const TaskRecord* sampled_memory_task = SampleTaskByMemory();
356 if (sampled_memory_task) {
357 std::unique_ptr<rappor::Sample> memory_sample(
358 CreateRapporSample(rappor_service, *sampled_memory_task));
359 memory_sample->SetFlagsField(
360 kRapporUsageRangeFlagsField,
361 GET_ENUM_VAL(GetMemoryUsageRange(sampled_memory_task->memory_bytes)),
362 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
363 rappor_service->RecordSampleObj(kMemoryRapporMetric,
364 std::move(memory_sample));
365 }
366 }
367
357 void ResourceReporter::OnMemoryPressure( 368 void ResourceReporter::OnMemoryPressure(
358 MemoryPressureLevel memory_pressure_level) { 369 MemoryPressureLevel memory_pressure_level) {
359 if (have_seen_first_task_manager_refresh_ && 370 if (memory_pressure_level ==
360 memory_pressure_level ==
361 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) { 371 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) {
362 // Report browser and GPU processes usage using UMA histograms.
363 UMA_HISTOGRAM_ENUMERATION(
364 "ResourceReporter.BrowserProcess.CpuUsage",
365 GET_ENUM_VAL(GetCpuUsageRange(last_browser_process_cpu_)),
366 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
367 UMA_HISTOGRAM_ENUMERATION(
368 "ResourceReporter.BrowserProcess.MemoryUsage",
369 GET_ENUM_VAL(GetMemoryUsageRange(last_browser_process_memory_)),
370 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
371 UMA_HISTOGRAM_ENUMERATION(
372 "ResourceReporter.GpuProcess.CpuUsage",
373 GET_ENUM_VAL(GetCpuUsageRange(last_gpu_process_cpu_)),
374 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
375 UMA_HISTOGRAM_ENUMERATION(
376 "ResourceReporter.GpuProcess.MemoryUsage",
377 GET_ENUM_VAL(GetMemoryUsageRange(last_gpu_process_memory_)),
378 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
379
380 // For the rest of tasks, report them using Rappor.
381 auto* rappor_service = g_browser_process->rappor_service();
382 if (!rappor_service)
383 return;
384
385 // We only record Rappor samples only if it's the first ever critical memory 372 // We only record Rappor samples only if it's the first ever critical memory
386 // pressure event we receive, or it has been more than 373 // pressure event we receive, or it has been more than
387 // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples. 374 // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples.
388 if (!have_seen_first_memory_pressure_event_) { 375 if (g_browser_process->local_state()) {
389 have_seen_first_memory_pressure_event_ = true; 376 base::Time now = base::Time::NowFromSystemTime();
390 } else if ((base::TimeTicks::Now() - last_memory_pressure_event_time_) < 377 base::Time last_rappor_report_time =
391 base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenReportsInMs)) { 378 base::Time::FromDoubleT(g_browser_process->local_state()->GetDouble(
392 return; 379 kLastRapporReportTimeKey));
380 base::TimeDelta delta_since_last_report =
381 now > last_rappor_report_time ? now - last_rappor_report_time
382 : base::TimeDelta::Max();
383
384 if (delta_since_last_report < kMinimumTimeBetweenReports)
385 return;
393 } 386 }
394 387
395 last_memory_pressure_event_time_ = base::TimeTicks::Now(); 388 // Start listening to the task manager and wait for the first refresh event
396 389 // with background calculations completion.
397 // Use weighted random sampling to select a task to report in the CPU 390 if (!observed_task_manager())
398 // metric. 391 task_manager::TaskManagerInterface::GetTaskManager()->AddObserver(this);
399 const TaskRecord* sampled_cpu_task = SampleTaskByCpu();
400 if (sampled_cpu_task) {
401 std::unique_ptr<rappor::Sample> cpu_sample(
402 CreateRapporSample(rappor_service, *sampled_cpu_task));
403 cpu_sample->SetFlagsField(kRapporNumCoresRangeFlagsField,
404 GET_ENUM_VAL(system_cpu_cores_range_),
405 GET_ENUM_VAL(CpuCoresNumberRange::NUM_RANGES));
406 cpu_sample->SetFlagsField(
407 kRapporUsageRangeFlagsField,
408 GET_ENUM_VAL(GetCpuUsageRange(sampled_cpu_task->cpu_percent)),
409 GET_ENUM_VAL(CpuUsageRange::NUM_RANGES));
410 rappor_service->RecordSampleObj(kCpuRapporMetric, std::move(cpu_sample));
411 }
412
413 // Use weighted random sampling to select a task to report in the memory
414 // metric.
415 const TaskRecord* sampled_memory_task = SampleTaskByMemory();
416 if (sampled_memory_task) {
417 std::unique_ptr<rappor::Sample> memory_sample(
418 CreateRapporSample(rappor_service, *sampled_memory_task));
419 memory_sample->SetFlagsField(
420 kRapporUsageRangeFlagsField,
421 GET_ENUM_VAL(GetMemoryUsageRange(sampled_memory_task->memory_bytes)),
422 GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES));
423 rappor_service->RecordSampleObj(kMemoryRapporMetric,
424 std::move(memory_sample));
425 }
426 } 392 }
427 } 393 }
428 394
429 } // namespace chromeos 395 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698