Fire an error if a pref used in the UI is missing once all prefs are fetched.
[chromium-blink-merge.git] / chrome / browser / metrics / metrics_memory_details.cc
blob957cce02b479bc01b4f2df41c92d58d01ce989fd
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.
5 #include "chrome/browser/metrics/metrics_memory_details.h"
7 #include <vector>
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/nacl/common/nacl_process_type.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/common/content_constants.h"
15 #include "content/public/common/process_type.h"
17 MemoryGrowthTracker::MemoryGrowthTracker() {
20 MemoryGrowthTracker::~MemoryGrowthTracker() {
23 bool MemoryGrowthTracker::UpdateSample(base::ProcessId pid,
24 int sample,
25 int* diff) {
26 // |sample| is memory usage in kB.
27 const base::TimeTicks current_time = base::TimeTicks::Now();
28 std::map<base::ProcessId, int>::iterator found_size = memory_sizes_.find(pid);
29 if (found_size != memory_sizes_.end()) {
30 const int last_size = found_size->second;
31 std::map<base::ProcessId, base::TimeTicks>::iterator found_time =
32 times_.find(pid);
33 const base::TimeTicks last_time = found_time->second;
34 if (last_time < (current_time - base::TimeDelta::FromMinutes(30))) {
35 // Note that it is undefined how division of a negative integer gets
36 // rounded. |*diff| may have a difference of 1 from the correct number
37 // if |sample| < |last_size|. We ignore it as 1 is small enough.
38 *diff =
39 ((sample - last_size) * 30 / (current_time - last_time).InMinutes());
40 found_size->second = sample;
41 found_time->second = current_time;
42 return true;
44 // Skip if a last record is found less than 30 minutes ago.
45 } else {
46 // Not reporting if it's the first record for |pid|.
47 times_[pid] = current_time;
48 memory_sizes_[pid] = sample;
50 return false;
53 MetricsMemoryDetails::MetricsMemoryDetails(
54 const base::Closure& callback,
55 MemoryGrowthTracker* memory_growth_tracker)
56 : callback_(callback), memory_growth_tracker_(memory_growth_tracker) {
57 memory_growth_tracker_ = memory_growth_tracker;
60 MetricsMemoryDetails::~MetricsMemoryDetails() {
63 void MetricsMemoryDetails::OnDetailsAvailable() {
64 UpdateHistograms();
65 base::MessageLoop::current()->PostTask(FROM_HERE, callback_);
68 void MetricsMemoryDetails::UpdateHistograms() {
69 // Reports a set of memory metrics to UMA.
70 // Memory is measured in KB.
72 const ProcessData& browser = *ChromeBrowser();
73 size_t aggregate_memory = 0;
74 int chrome_count = 0;
75 int extension_count = 0;
76 int plugin_count = 0;
77 int pepper_plugin_count = 0;
78 int pepper_plugin_broker_count = 0;
79 int renderer_count = 0;
80 int other_count = 0;
81 int worker_count = 0;
82 int process_limit = content::RenderProcessHost::GetMaxRendererProcessCount();
83 for (size_t index = 0; index < browser.processes.size(); index++) {
84 int sample = static_cast<int>(browser.processes[index].working_set.priv);
85 aggregate_memory += sample;
86 switch (browser.processes[index].process_type) {
87 case content::PROCESS_TYPE_BROWSER:
88 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
89 continue;
90 case content::PROCESS_TYPE_RENDERER: {
91 ProcessMemoryInformation::RendererProcessType renderer_type =
92 browser.processes[index].renderer_type;
93 switch (renderer_type) {
94 case ProcessMemoryInformation::RENDERER_EXTENSION:
95 UMA_HISTOGRAM_MEMORY_KB("Memory.Extension", sample);
96 extension_count++;
97 continue;
98 case ProcessMemoryInformation::RENDERER_CHROME:
99 UMA_HISTOGRAM_MEMORY_KB("Memory.Chrome", sample);
100 chrome_count++;
101 continue;
102 case ProcessMemoryInformation::RENDERER_UNKNOWN:
103 NOTREACHED() << "Unknown renderer process type.";
104 continue;
105 case ProcessMemoryInformation::RENDERER_NORMAL:
106 default:
107 // TODO(erikkay): Should we bother splitting out the other subtypes?
108 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
109 int diff;
110 if (memory_growth_tracker_ &&
111 memory_growth_tracker_->UpdateSample(
112 browser.processes[index].pid, sample, &diff)) {
113 if (diff < 0)
114 UMA_HISTOGRAM_MEMORY_KB("Memory.RendererShrinkIn30Min", -diff);
115 else
116 UMA_HISTOGRAM_MEMORY_KB("Memory.RendererGrowthIn30Min", diff);
118 renderer_count++;
119 continue;
122 case content::PROCESS_TYPE_PLUGIN:
123 UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
124 plugin_count++;
125 continue;
126 case content::PROCESS_TYPE_UTILITY:
127 UMA_HISTOGRAM_MEMORY_KB("Memory.Utility", sample);
128 other_count++;
129 continue;
130 case content::PROCESS_TYPE_ZYGOTE:
131 UMA_HISTOGRAM_MEMORY_KB("Memory.Zygote", sample);
132 other_count++;
133 continue;
134 case content::PROCESS_TYPE_SANDBOX_HELPER:
135 UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample);
136 other_count++;
137 continue;
138 case content::PROCESS_TYPE_GPU:
139 UMA_HISTOGRAM_MEMORY_KB("Memory.Gpu", sample);
140 other_count++;
141 continue;
142 #if defined(ENABLE_PLUGINS)
143 case content::PROCESS_TYPE_PPAPI_PLUGIN: {
144 const std::vector<base::string16>& titles =
145 browser.processes[index].titles;
146 if (titles.size() == 1 &&
147 titles[0] == base::ASCIIToUTF16(content::kFlashPluginName)) {
148 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperFlashPlugin", sample);
150 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPlugin", sample);
151 pepper_plugin_count++;
152 continue;
154 case content::PROCESS_TYPE_PPAPI_BROKER:
155 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPluginBroker", sample);
156 pepper_plugin_broker_count++;
157 continue;
158 #endif
159 case PROCESS_TYPE_NACL_LOADER:
160 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample);
161 other_count++;
162 continue;
163 case PROCESS_TYPE_NACL_BROKER:
164 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClientBroker", sample);
165 other_count++;
166 continue;
167 default:
168 NOTREACHED();
169 continue;
172 #if defined(OS_CHROMEOS)
173 // Chrome OS exposes system-wide graphics driver memory which has historically
174 // been a source of leak/bloat.
175 base::SystemMemoryInfoKB meminfo;
176 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1)
177 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
178 #endif
180 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
181 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
182 static_cast<int>(browser.processes.size()));
183 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
184 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
185 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
186 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
187 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
188 pepper_plugin_count);
189 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
190 pepper_plugin_broker_count);
191 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
192 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
193 // TODO(viettrungluu): Do we want separate counts for the other
194 // (platform-specific) process types?
196 int total_sample = static_cast<int>(aggregate_memory / 1000);
197 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
199 #if defined(OS_CHROMEOS)
200 UpdateSwapHistograms();
201 #endif
204 #if defined(OS_CHROMEOS)
205 void MetricsMemoryDetails::UpdateSwapHistograms() {
206 UMA_HISTOGRAM_BOOLEAN("Memory.Swap.HaveSwapped", swap_info().num_writes > 0);
207 if (swap_info().num_writes == 0)
208 return;
210 // Only record swap info when any swaps have happened, to give us more
211 // detail in the histograms.
212 const ProcessData& browser = *ChromeBrowser();
213 size_t aggregate_memory = 0;
214 for (size_t index = 0; index < browser.processes.size(); index++) {
215 int sample = static_cast<int>(browser.processes[index].working_set.swapped);
216 aggregate_memory += sample;
217 switch (browser.processes[index].process_type) {
218 case content::PROCESS_TYPE_BROWSER:
219 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Browser", sample);
220 continue;
221 case content::PROCESS_TYPE_RENDERER: {
222 ProcessMemoryInformation::RendererProcessType renderer_type =
223 browser.processes[index].renderer_type;
224 switch (renderer_type) {
225 case ProcessMemoryInformation::RENDERER_EXTENSION:
226 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Extension", sample);
227 continue;
228 case ProcessMemoryInformation::RENDERER_CHROME:
229 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Chrome", sample);
230 continue;
231 case ProcessMemoryInformation::RENDERER_UNKNOWN:
232 NOTREACHED() << "Unknown renderer process type.";
233 continue;
234 case ProcessMemoryInformation::RENDERER_NORMAL:
235 default:
236 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Renderer", sample);
237 continue;
240 case content::PROCESS_TYPE_PLUGIN:
241 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Plugin", sample);
242 continue;
243 case content::PROCESS_TYPE_UTILITY:
244 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Utility", sample);
245 continue;
246 case content::PROCESS_TYPE_ZYGOTE:
247 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Zygote", sample);
248 continue;
249 case content::PROCESS_TYPE_SANDBOX_HELPER:
250 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.SandboxHelper", sample);
251 continue;
252 case content::PROCESS_TYPE_GPU:
253 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Gpu", sample);
254 continue;
255 case content::PROCESS_TYPE_PPAPI_PLUGIN:
256 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPlugin", sample);
257 continue;
258 case content::PROCESS_TYPE_PPAPI_BROKER:
259 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPluginBroker", sample);
260 continue;
261 case PROCESS_TYPE_NACL_LOADER:
262 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClient", sample);
263 continue;
264 case PROCESS_TYPE_NACL_BROKER:
265 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClientBroker", sample);
266 continue;
267 default:
268 NOTREACHED();
269 continue;
273 int total_sample = static_cast<int>(aggregate_memory / 1000);
274 UMA_HISTOGRAM_MEMORY_MB("Memory.Swap.Total", total_sample);
276 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.CompressedDataSize",
277 swap_info().compr_data_size / (1024 * 1024), 1,
278 4096, 50);
279 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.OriginalDataSize",
280 swap_info().orig_data_size / (1024 * 1024), 1,
281 4096, 50);
282 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.MemUsedTotal",
283 swap_info().mem_used_total / (1024 * 1024), 1,
284 4096, 50);
285 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumReads", swap_info().num_reads, 1,
286 100000000, 100);
287 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumWrites", swap_info().num_writes,
288 1, 100000000, 100);
290 if (swap_info().orig_data_size > 0 && swap_info().compr_data_size > 0) {
291 UMA_HISTOGRAM_CUSTOM_COUNTS(
292 "Memory.Swap.CompressionRatio",
293 swap_info().orig_data_size / swap_info().compr_data_size, 1, 20, 20);
296 #endif // defined(OS_CHROMEOS)