Fix sorting issues in chrome_browser.gypi restructuring
[chromium-blink-merge.git] / chrome / browser / memory_details.cc
blobb2d22fbb67c4f0c17a20b5cabb9d7f39bd899dc9
1 // Copyright (c) 2012 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/memory_details.h"
7 #include "base/bind.h"
8 #include "base/file_version_info.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "components/nacl/common/nacl_process_type.h"
17 #include "content/public/browser/browser_child_process_host_iterator.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/child_process_data.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/render_widget_host_iterator.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/common/bindings_policy.h"
27 #include "content/public/common/content_constants.h"
28 #include "ui/base/l10n/l10n_util.h"
30 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
31 #include "content/public/browser/zygote_host_linux.h"
32 #endif
34 #if defined(ENABLE_EXTENSIONS)
35 #include "extensions/browser/extension_registry.h"
36 #include "extensions/browser/process_manager.h"
37 #include "extensions/browser/process_map.h"
38 #include "extensions/browser/view_type_utils.h"
39 #include "extensions/common/extension.h"
40 #endif
42 using base::StringPrintf;
43 using content::BrowserChildProcessHostIterator;
44 using content::BrowserThread;
45 using content::NavigationEntry;
46 using content::RenderViewHost;
47 using content::RenderWidgetHost;
48 using content::WebContents;
49 #if defined(ENABLE_EXTENSIONS)
50 using extensions::Extension;
51 #endif
53 // static
54 std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish(
55 RendererProcessType type) {
56 switch (type) {
57 case RENDERER_NORMAL:
58 return "Tab";
59 case RENDERER_CHROME:
60 return "Tab (Chrome)";
61 case RENDERER_EXTENSION:
62 return "Extension";
63 case RENDERER_DEVTOOLS:
64 return "Devtools";
65 case RENDERER_INTERSTITIAL:
66 return "Interstitial";
67 case RENDERER_BACKGROUND_APP:
68 return "Background App";
69 case RENDERER_UNKNOWN:
70 default:
71 NOTREACHED() << "Unknown renderer process type!";
72 return "Unknown";
76 // static
77 std::string ProcessMemoryInformation::GetFullTypeNameInEnglish(
78 int process_type,
79 RendererProcessType rtype) {
80 if (process_type == content::PROCESS_TYPE_RENDERER)
81 return GetRendererTypeNameInEnglish(rtype);
82 return content::GetProcessTypeNameInEnglish(process_type);
85 ProcessMemoryInformation::ProcessMemoryInformation()
86 : pid(0),
87 num_processes(0),
88 is_diagnostics(false),
89 process_type(content::PROCESS_TYPE_UNKNOWN),
90 renderer_type(RENDERER_UNKNOWN) {
93 ProcessMemoryInformation::~ProcessMemoryInformation() {}
95 bool ProcessMemoryInformation::operator<(
96 const ProcessMemoryInformation& rhs) const {
97 return working_set.priv < rhs.working_set.priv;
100 ProcessData::ProcessData() {}
102 ProcessData::ProcessData(const ProcessData& rhs)
103 : name(rhs.name),
104 process_name(rhs.process_name),
105 processes(rhs.processes) {
108 ProcessData::~ProcessData() {}
110 ProcessData& ProcessData::operator=(const ProcessData& rhs) {
111 name = rhs.name;
112 process_name = rhs.process_name;
113 processes = rhs.processes;
114 return *this;
117 MemoryGrowthTracker::MemoryGrowthTracker() {}
119 MemoryGrowthTracker::~MemoryGrowthTracker() {}
121 bool MemoryGrowthTracker::UpdateSample(
122 base::ProcessId pid,
123 int sample,
124 int* diff) {
125 // |sample| is memory usage in kB.
126 const base::TimeTicks current_time = base::TimeTicks::Now();
127 std::map<base::ProcessId, int>::iterator found_size = memory_sizes_.find(pid);
128 if (found_size != memory_sizes_.end()) {
129 const int last_size = found_size->second;
130 std::map<base::ProcessId, base::TimeTicks>::iterator found_time =
131 times_.find(pid);
132 const base::TimeTicks last_time = found_time->second;
133 if (last_time < (current_time - base::TimeDelta::FromMinutes(30))) {
134 // Note that it is undefined how division of a negative integer gets
135 // rounded. |*diff| may have a difference of 1 from the correct number
136 // if |sample| < |last_size|. We ignore it as 1 is small enough.
137 *diff = ((sample - last_size) * 30 /
138 (current_time - last_time).InMinutes());
139 found_size->second = sample;
140 found_time->second = current_time;
141 return true;
143 // Skip if a last record is found less than 30 minutes ago.
144 } else {
145 // Not reporting if it's the first record for |pid|.
146 times_[pid] = current_time;
147 memory_sizes_[pid] = sample;
149 return false;
152 // About threading:
154 // This operation will hit no fewer than 3 threads.
156 // The BrowserChildProcessHostIterator can only be accessed from the IO thread.
158 // The RenderProcessHostIterator can only be accessed from the UI thread.
160 // This operation can take 30-100ms to complete. We never want to have
161 // one task run for that long on the UI or IO threads. So, we run the
162 // expensive parts of this operation over on the file thread.
164 void MemoryDetails::StartFetch(UserMetricsMode user_metrics_mode) {
165 // This might get called from the UI or FILE threads, but should not be
166 // getting called from the IO thread.
167 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
168 user_metrics_mode_ = user_metrics_mode;
170 // In order to process this request, we need to use the plugin information.
171 // However, plugin process information is only available from the IO thread.
172 BrowserThread::PostTask(
173 BrowserThread::IO, FROM_HERE,
174 base::Bind(&MemoryDetails::CollectChildInfoOnIOThread, this));
177 MemoryDetails::~MemoryDetails() {}
179 std::string MemoryDetails::ToLogString() {
180 std::string log;
181 log.reserve(4096);
182 ProcessMemoryInformationList processes = ChromeBrowser()->processes;
183 // Sort by memory consumption, low to high.
184 std::sort(processes.begin(), processes.end());
185 // Print from high to low.
186 for (ProcessMemoryInformationList::reverse_iterator iter1 =
187 processes.rbegin();
188 iter1 != processes.rend();
189 ++iter1) {
190 log += ProcessMemoryInformation::GetFullTypeNameInEnglish(
191 iter1->process_type, iter1->renderer_type);
192 if (!iter1->titles.empty()) {
193 log += " [";
194 for (std::vector<base::string16>::const_iterator iter2 =
195 iter1->titles.begin();
196 iter2 != iter1->titles.end(); ++iter2) {
197 if (iter2 != iter1->titles.begin())
198 log += "|";
199 log += base::UTF16ToUTF8(*iter2);
201 log += "]";
203 log += StringPrintf(" %d MB private, %d MB shared",
204 static_cast<int>(iter1->working_set.priv) / 1024,
205 static_cast<int>(iter1->working_set.shared) / 1024);
206 #if defined(OS_CHROMEOS)
207 log += StringPrintf(", %d MB swapped",
208 static_cast<int>(iter1->working_set.swapped) / 1024);
209 #endif
210 log += "\n";
212 return log;
215 void MemoryDetails::SetMemoryGrowthTracker(
216 MemoryGrowthTracker* memory_growth_tracker) {
217 memory_growth_tracker_ = memory_growth_tracker;
220 void MemoryDetails::CollectChildInfoOnIOThread() {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
223 std::vector<ProcessMemoryInformation> child_info;
225 // Collect the list of child processes. A 0 |handle| means that
226 // the process is being launched, so we skip it.
227 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
228 ProcessMemoryInformation info;
229 if (!iter.GetData().handle)
230 continue;
231 info.pid = base::GetProcId(iter.GetData().handle);
232 if (!info.pid)
233 continue;
235 info.process_type = iter.GetData().process_type;
236 info.renderer_type = ProcessMemoryInformation::RENDERER_UNKNOWN;
237 info.titles.push_back(iter.GetData().name);
238 child_info.push_back(info);
241 // Now go do expensive memory lookups from the file thread.
242 BrowserThread::PostTask(
243 BrowserThread::FILE, FROM_HERE,
244 base::Bind(&MemoryDetails::CollectProcessData, this, child_info));
247 void MemoryDetails::CollectChildInfoOnUIThread() {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
251 const pid_t zygote_pid = content::ZygoteHost::GetInstance()->GetPid();
252 #endif
254 ProcessData* const chrome_browser = ChromeBrowser();
255 // Get more information about the process.
256 for (size_t index = 0; index < chrome_browser->processes.size();
257 index++) {
258 // Check if it's a renderer, if so get the list of page titles in it and
259 // check if it's a diagnostics-related process. We skip about:memory pages.
260 // Iterate the RenderProcessHosts to find the tab contents.
261 ProcessMemoryInformation& process =
262 chrome_browser->processes[index];
264 scoped_ptr<content::RenderWidgetHostIterator> widgets(
265 RenderWidgetHost::GetRenderWidgetHosts());
266 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
267 content::RenderProcessHost* render_process_host =
268 widget->GetProcess();
269 DCHECK(render_process_host);
270 // Ignore processes that don't have a connection, such as crashed tabs.
271 if (!render_process_host->HasConnection() ||
272 process.pid != base::GetProcId(render_process_host->GetHandle())) {
273 continue;
276 // The RenderProcessHost may host multiple WebContentses. Any
277 // of them which contain diagnostics information make the whole
278 // process be considered a diagnostics process.
279 if (!widget->IsRenderView())
280 continue;
282 process.process_type = content::PROCESS_TYPE_RENDERER;
283 bool is_extension = false;
284 RenderViewHost* host = RenderViewHost::From(widget);
285 #if defined(ENABLE_EXTENSIONS)
286 content::BrowserContext* context =
287 render_process_host->GetBrowserContext();
288 extensions::ExtensionRegistry* extension_registry =
289 extensions::ExtensionRegistry::Get(context);
290 extensions::ProcessMap* extension_process_map =
291 extensions::ProcessMap::Get(context);
292 is_extension = extension_process_map->Contains(
293 host->GetProcess()->GetID());
294 #endif
296 WebContents* contents = WebContents::FromRenderViewHost(host);
297 GURL url;
298 if (contents) {
299 url = contents->GetURL();
300 SiteData* site_data =
301 &chrome_browser->site_data[contents->GetBrowserContext()];
302 SiteDetails::CollectSiteInfo(contents, site_data);
304 #if defined(ENABLE_EXTENSIONS)
305 extensions::ViewType type = extensions::GetViewType(contents);
306 #endif
307 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
308 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
309 } else if (is_extension) {
310 #if defined(ENABLE_EXTENSIONS)
311 // For our purposes, don't count processes containing only hosted apps
312 // as extension processes. See also: crbug.com/102533.
313 std::set<std::string> extension_ids =
314 extension_process_map->GetExtensionsInProcess(
315 host->GetProcess()->GetID());
316 for (std::set<std::string>::iterator iter = extension_ids.begin();
317 iter != extension_ids.end(); ++iter) {
318 const Extension* extension =
319 extension_registry->enabled_extensions().GetByID(*iter);
320 if (extension && !extension->is_hosted_app()) {
321 process.renderer_type =
322 ProcessMemoryInformation::RENDERER_EXTENSION;
323 break;
326 #endif
328 #if defined(ENABLE_EXTENSIONS)
329 if (is_extension) {
330 const Extension* extension =
331 extension_registry->enabled_extensions().GetByID(url.host());
332 if (extension) {
333 base::string16 title = base::UTF8ToUTF16(extension->name());
334 process.titles.push_back(title);
335 process.renderer_type =
336 ProcessMemoryInformation::RENDERER_EXTENSION;
337 continue;
340 #endif
342 if (!contents) {
343 process.renderer_type =
344 ProcessMemoryInformation::RENDERER_INTERSTITIAL;
345 continue;
348 #if defined(ENABLE_EXTENSIONS)
349 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
350 process.titles.push_back(base::UTF8ToUTF16(url.spec()));
351 process.renderer_type =
352 ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
353 continue;
355 #endif
357 // Since we have a WebContents and and the renderer type hasn't been
358 // set yet, it must be a normal tabbed renderer.
359 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
360 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
362 base::string16 title = contents->GetTitle();
363 if (!title.length())
364 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
365 process.titles.push_back(title);
367 // We need to check the pending entry as well as the virtual_url to
368 // see if it's a chrome://memory URL (we don't want to count these in
369 // the total memory usage of the browser).
371 // When we reach here, chrome://memory will be the pending entry since
372 // we haven't responded with any data such that it would be committed.
373 // If you have another chrome://memory tab open (which would be
374 // committed), we don't want to count it either, so we also check the
375 // last committed entry.
377 // Either the pending or last committed entries can be NULL.
378 const NavigationEntry* pending_entry =
379 contents->GetController().GetPendingEntry();
380 const NavigationEntry* last_committed_entry =
381 contents->GetController().GetLastCommittedEntry();
382 if ((last_committed_entry &&
383 LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(),
384 chrome::kChromeUIMemoryURL)) ||
385 (pending_entry &&
386 LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(),
387 chrome::kChromeUIMemoryURL))) {
388 process.is_diagnostics = true;
392 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
393 if (process.pid == zygote_pid) {
394 process.process_type = content::PROCESS_TYPE_ZYGOTE;
396 #endif
399 // Get rid of other Chrome processes that are from a different profile.
400 for (size_t index = 0; index < chrome_browser->processes.size();
401 index++) {
402 if (chrome_browser->processes[index].process_type ==
403 content::PROCESS_TYPE_UNKNOWN) {
404 chrome_browser->processes.erase(
405 chrome_browser->processes.begin() + index);
406 index--;
410 if (user_metrics_mode_ == UPDATE_USER_METRICS)
411 UpdateHistograms();
413 OnDetailsAvailable();
416 void MemoryDetails::UpdateHistograms() {
417 // Reports a set of memory metrics to UMA.
418 // Memory is measured in KB.
420 const ProcessData& browser = *ChromeBrowser();
421 size_t aggregate_memory = 0;
422 int chrome_count = 0;
423 int extension_count = 0;
424 int plugin_count = 0;
425 int pepper_plugin_count = 0;
426 int pepper_plugin_broker_count = 0;
427 int renderer_count = 0;
428 int other_count = 0;
429 int worker_count = 0;
430 int process_limit = content::RenderProcessHost::GetMaxRendererProcessCount();
431 for (size_t index = 0; index < browser.processes.size(); index++) {
432 int sample = static_cast<int>(browser.processes[index].working_set.priv);
433 aggregate_memory += sample;
434 switch (browser.processes[index].process_type) {
435 case content::PROCESS_TYPE_BROWSER:
436 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
437 continue;
438 case content::PROCESS_TYPE_RENDERER: {
439 ProcessMemoryInformation::RendererProcessType renderer_type =
440 browser.processes[index].renderer_type;
441 switch (renderer_type) {
442 case ProcessMemoryInformation::RENDERER_EXTENSION:
443 UMA_HISTOGRAM_MEMORY_KB("Memory.Extension", sample);
444 extension_count++;
445 continue;
446 case ProcessMemoryInformation::RENDERER_CHROME:
447 UMA_HISTOGRAM_MEMORY_KB("Memory.Chrome", sample);
448 chrome_count++;
449 continue;
450 case ProcessMemoryInformation::RENDERER_UNKNOWN:
451 NOTREACHED() << "Unknown renderer process type.";
452 continue;
453 case ProcessMemoryInformation::RENDERER_NORMAL:
454 default:
455 // TODO(erikkay): Should we bother splitting out the other subtypes?
456 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
457 int diff;
458 if (memory_growth_tracker_ &&
459 memory_growth_tracker_->UpdateSample(
460 browser.processes[index].pid, sample, &diff)) {
461 if (diff < 0)
462 UMA_HISTOGRAM_MEMORY_KB("Memory.RendererShrinkIn30Min", -diff);
463 else
464 UMA_HISTOGRAM_MEMORY_KB("Memory.RendererGrowthIn30Min", diff);
466 renderer_count++;
467 continue;
470 case content::PROCESS_TYPE_PLUGIN:
471 UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
472 plugin_count++;
473 continue;
474 case content::PROCESS_TYPE_UTILITY:
475 UMA_HISTOGRAM_MEMORY_KB("Memory.Utility", sample);
476 other_count++;
477 continue;
478 case content::PROCESS_TYPE_ZYGOTE:
479 UMA_HISTOGRAM_MEMORY_KB("Memory.Zygote", sample);
480 other_count++;
481 continue;
482 case content::PROCESS_TYPE_SANDBOX_HELPER:
483 UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample);
484 other_count++;
485 continue;
486 case content::PROCESS_TYPE_GPU:
487 UMA_HISTOGRAM_MEMORY_KB("Memory.Gpu", sample);
488 other_count++;
489 continue;
490 #if defined(ENABLE_PLUGINS)
491 case content::PROCESS_TYPE_PPAPI_PLUGIN:
493 const std::vector<base::string16>& titles =
494 browser.processes[index].titles;
495 if (titles.size() == 1 &&
496 titles[0] == base::ASCIIToUTF16(content::kFlashPluginName)) {
497 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperFlashPlugin", sample);
500 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPlugin", sample);
501 pepper_plugin_count++;
502 continue;
503 case content::PROCESS_TYPE_PPAPI_BROKER:
504 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPluginBroker", sample);
505 pepper_plugin_broker_count++;
506 continue;
507 #endif
508 case PROCESS_TYPE_NACL_LOADER:
509 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample);
510 other_count++;
511 continue;
512 case PROCESS_TYPE_NACL_BROKER:
513 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClientBroker", sample);
514 other_count++;
515 continue;
516 default:
517 NOTREACHED();
518 continue;
521 #if defined(OS_CHROMEOS)
522 // Chrome OS exposes system-wide graphics driver memory which has historically
523 // been a source of leak/bloat.
524 base::SystemMemoryInfoKB meminfo;
525 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1)
526 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
527 #endif
529 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
530 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
531 static_cast<int>(browser.processes.size()));
532 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
533 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
534 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
535 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
536 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
537 pepper_plugin_count);
538 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
539 pepper_plugin_broker_count);
540 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
541 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
542 // TODO(viettrungluu): Do we want separate counts for the other
543 // (platform-specific) process types?
545 int total_sample = static_cast<int>(aggregate_memory / 1000);
546 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
548 #if defined(OS_CHROMEOS)
549 UpdateSwapHistograms();
550 #endif
553 #if defined(OS_CHROMEOS)
554 void MemoryDetails::UpdateSwapHistograms() {
555 UMA_HISTOGRAM_BOOLEAN("Memory.Swap.HaveSwapped", swap_info_.num_writes > 0);
556 if (swap_info_.num_writes == 0)
557 return;
559 // Only record swap info when any swaps have happened, to give us more
560 // detail in the histograms.
561 const ProcessData& browser = *ChromeBrowser();
562 size_t aggregate_memory = 0;
563 for (size_t index = 0; index < browser.processes.size(); index++) {
564 int sample = static_cast<int>(browser.processes[index].working_set.swapped);
565 aggregate_memory += sample;
566 switch (browser.processes[index].process_type) {
567 case content::PROCESS_TYPE_BROWSER:
568 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Browser", sample);
569 continue;
570 case content::PROCESS_TYPE_RENDERER: {
571 ProcessMemoryInformation::RendererProcessType renderer_type =
572 browser.processes[index].renderer_type;
573 switch (renderer_type) {
574 case ProcessMemoryInformation::RENDERER_EXTENSION:
575 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Extension", sample);
576 continue;
577 case ProcessMemoryInformation::RENDERER_CHROME:
578 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Chrome", sample);
579 continue;
580 case ProcessMemoryInformation::RENDERER_UNKNOWN:
581 NOTREACHED() << "Unknown renderer process type.";
582 continue;
583 case ProcessMemoryInformation::RENDERER_NORMAL:
584 default:
585 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Renderer", sample);
586 continue;
589 case content::PROCESS_TYPE_PLUGIN:
590 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Plugin", sample);
591 continue;
592 case content::PROCESS_TYPE_UTILITY:
593 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Utility", sample);
594 continue;
595 case content::PROCESS_TYPE_ZYGOTE:
596 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Zygote", sample);
597 continue;
598 case content::PROCESS_TYPE_SANDBOX_HELPER:
599 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.SandboxHelper", sample);
600 continue;
601 case content::PROCESS_TYPE_GPU:
602 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Gpu", sample);
603 continue;
604 case content::PROCESS_TYPE_PPAPI_PLUGIN:
605 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPlugin", sample);
606 continue;
607 case content::PROCESS_TYPE_PPAPI_BROKER:
608 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPluginBroker", sample);
609 continue;
610 case PROCESS_TYPE_NACL_LOADER:
611 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClient", sample);
612 continue;
613 case PROCESS_TYPE_NACL_BROKER:
614 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClientBroker", sample);
615 continue;
616 default:
617 NOTREACHED();
618 continue;
622 int total_sample = static_cast<int>(aggregate_memory / 1000);
623 UMA_HISTOGRAM_MEMORY_MB("Memory.Swap.Total", total_sample);
625 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.CompressedDataSize",
626 swap_info_.compr_data_size / (1024 * 1024),
627 1, 4096, 50);
628 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.OriginalDataSize",
629 swap_info_.orig_data_size / (1024 * 1024),
630 1, 4096, 50);
631 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.MemUsedTotal",
632 swap_info_.mem_used_total / (1024 * 1024),
633 1, 4096, 50);
634 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumReads",
635 swap_info_.num_reads,
636 1, 100000000, 100);
637 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumWrites",
638 swap_info_.num_writes,
639 1, 100000000, 100);
641 if (swap_info_.orig_data_size > 0 && swap_info_.compr_data_size > 0) {
642 UMA_HISTOGRAM_CUSTOM_COUNTS(
643 "Memory.Swap.CompressionRatio",
644 swap_info_.orig_data_size / swap_info_.compr_data_size,
645 1, 20, 20);
649 #endif // defined(OS_CHROMEOS)