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