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

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

Issue 1374283003: Reporting top cpu and memory consumers via rappor on chromeos (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: browser/gpu stats by UMA histograms, buckets for cpu cores. Created 5 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_
6 #define CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_
7
8 #include <map>
9 #include <set>
10
11 #include "base/gtest_prod_util.h"
12 #include "base/macros.h"
13 #include "base/memory/memory_pressure_listener.h"
14 #include "chrome/browser/task_management/task_manager_observer.h"
15 #include "components/metrics/metrics_service.h"
16 #include "components/rappor/sample.h"
17
18 namespace base {
19 template <typename T>
20 struct DefaultSingletonTraits;
21 }
22
23 using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
24
25 namespace chromeos {
26
27 // A system that tracks the top |kTopConsumersCount| CPU and memory consumer
28 // Chrome tasks and reports them via Rappor whenever memory pressure is moderate
29 // or higher.
30 class ResourceReporter
31 : public task_management::TaskManagerObserver,
32 public metrics::MetricsServiceObserver {
33 public:
34 // A collection of the data of a task manager's task that the ResourceReporter
35 // is interested in.
36 struct TaskRecord {
37 // The ID of the task.
38 task_management::TaskId id;
39
40 // The name of the Rappor sample to be used for recording a sample
41 // representing this task.
42 std::string rappor_sample;
43
44 // The CPU usage of the task from most recent task manager refresh.
ncarter (slow) 2015/11/10 23:29:56 Is this a percentage? Clarify the comment.
afakhry 2015/11/12 00:21:28 Done.
45 double cpu;
46
47 // The physical memory usage of the task from the most recent task manager
48 // refresh.
ncarter (slow) 2015/11/10 23:29:56 In bytes? Does this include shared memory?
afakhry 2015/11/12 00:21:28 Done.
49 int64_t memory;
50
51 // True if the task is running on backgrounded process.
ncarter (slow) 2015/11/10 23:29:56 "running at background priority" might be a better
afakhry 2015/11/12 00:21:28 Done.
52 bool is_background;
53
54 explicit TaskRecord(task_management::TaskId the_id)
55 : id(the_id), cpu(0.0), memory(0), is_background(false) {}
56
57 TaskRecord(task_management::TaskId the_id,
58 const std::string& the_sample,
59 double the_cpu,
60 int64_t the_memory,
61 bool background)
ncarter (slow) 2015/11/10 23:29:56 Should be in the .cc file.
afakhry 2015/11/12 00:21:28 Done.
62 : id(the_id),
63 rappor_sample(the_sample),
64 cpu(the_cpu),
65 memory(the_memory),
66 is_background(background) {}
67 };
68
69 ~ResourceReporter() override;
70
71 // The system runs only if the user has opted-in to send anonymous usage stats
72 // to Google. We observe state changes in the MetricsService which will
ncarter (slow) 2015/11/10 23:29:56 Is there a way to word this without saying "Google
afakhry 2015/11/12 00:21:28 Done.
73 // determine if the ResourceReporter needs to observe the task manager and
74 // collect resource usage stats.
75 static void StartObservingMetricsService();
76 static void StopObservingMetricsService();
77
78 // The singleton instance.
79 static ResourceReporter* GetInstance();
80
81 // task_management::TaskManagerObserver:
82 void OnTaskAdded(task_management::TaskId id) override;
83 void OnTaskToBeRemoved(task_management::TaskId id) override;
84 void OnTasksRefreshed(const task_management::TaskIdList& task_ids) override;
85
86 // metrics::MetricsServiceObserver:
87 void OnMetricsServiceStart() override;
88 void OnMetricsServiceStop() override;
89
90 private:
91 friend struct base::DefaultSingletonTraits<ResourceReporter>;
92 friend class ResourceReporterTest;
93 FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestGetCpuRapporMetricName);
94 FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestGetMemoryRapporMetricName);
95 FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestAll);
96
97 // A functor to sort the TaskRecords by their |cpu| in a descending order.
98 struct TaskRecordByCpuSorter {
99 bool operator()(TaskRecord* const& lhs, TaskRecord* const& rhs) const {
100 if (lhs->cpu == rhs->cpu)
ncarter (slow) 2015/11/10 23:29:56 This is a nontrivial function; shouldn't be in a h
afakhry 2015/11/12 00:21:28 Done and modified for both sorters to be a Less th
101 return lhs->id > rhs->id;
102 return lhs->cpu > rhs->cpu;
103 }
104 };
105
106 // A functor to sort the TaskRecords by their |memory| in a descending order.
107 struct TaskRecordByMemorySorter {
108 bool operator()(TaskRecord* const& lhs, TaskRecord* const& rhs) const {
109 if (lhs->memory == rhs->memory)
110 return lhs->id > rhs->id;
111 return lhs->memory > rhs->memory;
112 }
113 };
114
115 enum TaskProcessPriority {
116 FOREGROUND = 0,
117 BACKGROUND,
118 PRIORITIES_NUM,
119 };
120
121 enum CpuUsageRange {
122 RANGE_0_TO_10_PERCENT = 0,
123 RANGE_10_TO_30_PERCENT,
124 RANGE_30_TO_60_PERCENT,
125 RANGE_ABOVE_60_PERCENT,
126 CPU_RANGES_NUM,
127 };
128
129 enum MemoryUsageRange {
130 RANGE_0_TO_200_MB = 0,
131 RANGE_200_TO_400_MB,
132 RANGE_400_TO_600_MB,
133 RANGE_600_TO_800_MB,
134 RANGE_800_TO_1_GB,
135 RANGE_ABOVE_1_GB,
136 MEMORY_RANGES_NUM,
137 };
138
139 enum CpuCoresNumberRange {
140 RANGE_CORES_0_CORES = 0,
ncarter (slow) 2015/11/10 23:29:56 I've never seen a machine with 0 cores. How would
afakhry 2015/11/12 00:21:28 Done.
141 RANGE_CORES_1_TO_2_CORES, // [1, 2]
ncarter (slow) 2015/11/10 23:29:56 Should 1 and 2 cores be separate buckets?
afakhry 2015/11/12 00:21:28 Done.
142 RANGE_CORES_2_TO_4_CORES, // ]2, 4]
ncarter (slow) 2015/11/10 23:29:56 This "]2" notation (which I assume means an open i
afakhry 2015/11/12 00:21:28 Haha! Yes it means an open interval. We used to wr
143 RANGE_CORES_4_TO_8_CORES, // ]4, 8]
144 RANGE_CORES_8_TO_16_CORES, // ]8, 16]
145 RANGE_CORES_ABOVE_16_CORES, // > 16
146 CORES_RANGES_NUM,
147 };
148
149 // The maximum number of top consumer tasks of each resource that we're
150 // interested in reporting.
151 static const size_t kTopConsumersCount;
152
153 ResourceReporter();
154
155 // Creates a Rappor sample for the given |task_record|.
156 static scoped_ptr<rappor::Sample> CreateRapporSample(
157 rappor::RapporService* rappor_service,
158 const TaskRecord& task_record);
159
160 // Gets the CPU/memory usage ranges given the |cpu| / |memory_in_bytes|
161 // values.
162 static CpuUsageRange GetCpuUsageRange(double cpu);
163 static MemoryUsageRange GetMemoryUsageRange(int64_t memory_in_bytes);
164
165 // Gets the bucket in which the current system's number of CPU cores fall
166 // into.
167 static CpuCoresNumberRange GetCurrentSystemCpuCoresRange();
168
169 // Start / stop observing the task manager and the memory pressure events.
170 void StartMonitoring();
171 void StopMonitoring();
172
173 // The callback function that will be invoked on memory pressure events.
174 void OnMemoryPressure(MemoryPressureLevel memory_pressure_level);
175
176 // We'll use this to watch for memory pressure events so that we can trigger
177 // Rappor sampling at moderate memory pressure or higher.
178 scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_;
179
180 // Contains the collected data about the currently running tasks from the most
181 // recent task manager refresh.
182 std::map<task_management::TaskId, scoped_ptr<TaskRecord>> task_records_;
183
184 // Contains the top |kTopConsumerCount| CPU consumer tasks sorted in a
185 // descending order by their CPU usage.
186 std::set<TaskRecord*, TaskRecordByCpuSorter> task_records_by_cpu_;
187
188 // Contains the top |kTopConsumerCount| memory consumer tasks sorted in a
189 // descending order by their memory usage.
190 std::set<TaskRecord*, TaskRecordByMemorySorter> task_records_by_memory_;
191
192 const CpuCoresNumberRange system_cpu_cores_range_;
193
194 // the most recent reading for the browser and GPU processes to be reported as
195 // UMA histograms when the system is under moderate memory pressure or higher.
196 double last_browser_process_cpu_ = 0.0;
197 double last_gpu_process_cpu_ = 0.0;
198 int64_t last_browser_process_memory_ = 0;
199 int64_t last_gpu_process_memory_ = 0;
200
201 MemoryPressureLevel previous_memory_pressure_level_ =
202 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE;
203
204 // MetricsService::Start()/Stop() can be called multiple times which can cause
205 // all sort of trouble. We need to track whether we have already started
206 // monitoring or not using the below flag.
207 bool is_monitoring_;
ncarter (slow) 2015/11/10 23:29:56 This is kind of weird. Why are there redundant Sta
afakhry 2015/11/12 00:21:28 The problem happens when Start() is called several
ncarter (slow) 2015/11/13 22:44:32 Are we just coding around a bug in the MetricsServ
208
209 DISALLOW_COPY_AND_ASSIGN(ResourceReporter);
210 };
211
212 } // namespace chromeos
213
214 #endif // CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698