blob: 3e24154e58785108627eadfa2cd4d3f1a9b749aa [file] [log] [blame]
[email protected]b0b67cf2012-01-18 21:59:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/memory_details.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]24d69692011-10-21 18:26:517#include "base/bind.h"
initial.commit09911bf2008-07-26 23:55:298#include "base/file_version_info.h"
[email protected]835d7c82010-10-14 04:38:389#include "base/metrics/histogram.h"
[email protected]f9b294362013-06-10 20:22:3110#include "base/strings/string_util.h"
11#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1812#include "base/strings/utf_string_conversions.h"
[email protected]8add5412011-10-01 21:02:1413#include "chrome/browser/extensions/extension_process_manager.h"
[email protected]79dc42cd2011-01-08 21:43:3514#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/profiles/profile.h"
[email protected]fcf79352010-12-28 20:13:2016#include "chrome/common/extensions/extension.h"
[email protected]cd3d7892009-03-04 23:55:0617#include "chrome/common/url_constants.h"
[email protected]d5d383252013-07-04 14:44:3218#include "components/nacl/common/nacl_process_type.h"
[email protected]4967f792012-01-20 22:14:4019#include "content/public/browser/browser_child_process_host_iterator.h"
[email protected]c38831a12011-10-28 12:44:4920#include "content/public/browser/browser_thread.h"
[email protected]9c1662b2012-03-06 15:44:3321#include "content/public/browser/child_process_data.h"
[email protected]a53209b2012-01-20 16:48:1622#include "content/public/browser/navigation_controller.h"
[email protected]022af742011-12-28 18:37:2523#include "content/public/browser/navigation_entry.h"
[email protected]f3b1a082011-11-18 00:34:3024#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3325#include "content/public/browser/render_view_host.h"
[email protected]a801cb32013-09-11 18:02:2726#include "content/public/browser/render_widget_host_iterator.h"
[email protected]83ff91c2012-01-05 20:54:1327#include "content/public/browser/web_contents.h"
[email protected]e091df82011-10-11 18:13:2128#include "content/public/common/bindings_policy.h"
[email protected]cb2edf22013-04-01 20:25:2329#include "extensions/browser/view_type_utils.h"
[email protected]ae5ca892009-07-30 18:00:4730#include "grit/chromium_strings.h"
[email protected]4f260d02010-12-23 18:35:4231#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1732#include "ui/base/l10n/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2933
[email protected]a423c9e2012-03-06 18:02:3134#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]c2c68b1f2012-02-25 00:29:1535#include "content/public/browser/zygote_host_linux.h"
[email protected]54fd1d32009-09-01 00:12:5836#endif
initial.commit09911bf2008-07-26 23:55:2937
[email protected]4306df72012-04-20 18:58:5738using base::StringPrintf;
[email protected]4967f792012-01-20 22:14:4039using content::BrowserChildProcessHostIterator;
[email protected]631bb742011-11-02 11:29:3940using content::BrowserThread;
[email protected]10f417c52011-12-28 21:04:2341using content::NavigationEntry;
[email protected]eaabba22012-03-07 15:02:1142using content::RenderViewHost;
43using content::RenderWidgetHost;
[email protected]83ff91c2012-01-05 20:54:1344using content::WebContents;
[email protected]1c321ee2012-05-21 03:02:3445using extensions::Extension;
[email protected]631bb742011-11-02 11:29:3946
[email protected]2c1978a2011-11-29 17:02:3947// static
48std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish(
49 RendererProcessType type) {
50 switch (type) {
51 case RENDERER_NORMAL:
52 return "Tab";
53 case RENDERER_CHROME:
54 return "Tab (Chrome)";
55 case RENDERER_EXTENSION:
56 return "Extension";
57 case RENDERER_DEVTOOLS:
58 return "Devtools";
59 case RENDERER_INTERSTITIAL:
60 return "Interstitial";
61 case RENDERER_NOTIFICATION:
62 return "Notification";
63 case RENDERER_BACKGROUND_APP:
64 return "Background App";
65 case RENDERER_UNKNOWN:
66 default:
67 NOTREACHED() << "Unknown renderer process type!";
68 return "Unknown";
69 }
70}
71
72// static
73std::string ProcessMemoryInformation::GetFullTypeNameInEnglish(
[email protected]f3b357692013-03-22 05:16:1374 int process_type,
[email protected]2c1978a2011-11-29 17:02:3975 RendererProcessType rtype) {
[email protected]f3b357692013-03-22 05:16:1376 if (process_type == content::PROCESS_TYPE_RENDERER)
[email protected]2c1978a2011-11-29 17:02:3977 return GetRendererTypeNameInEnglish(rtype);
[email protected]f3b357692013-03-22 05:16:1378 return content::GetProcessTypeNameInEnglish(process_type);
[email protected]2c1978a2011-11-29 17:02:3979}
80
[email protected]8e383412010-10-19 16:57:0381ProcessMemoryInformation::ProcessMemoryInformation()
82 : pid(0),
83 num_processes(0),
84 is_diagnostics(false),
[email protected]f3b357692013-03-22 05:16:1385 process_type(content::PROCESS_TYPE_UNKNOWN),
[email protected]2c1978a2011-11-29 17:02:3986 renderer_type(RENDERER_UNKNOWN) {
[email protected]8e383412010-10-19 16:57:0387}
88
89ProcessMemoryInformation::~ProcessMemoryInformation() {}
90
[email protected]8e23c882012-05-05 01:14:1191bool ProcessMemoryInformation::operator<(
92 const ProcessMemoryInformation& rhs) const {
93 return working_set.priv < rhs.working_set.priv;
94}
95
[email protected]93aa89c72010-10-20 21:32:0496ProcessData::ProcessData() {}
97
98ProcessData::ProcessData(const ProcessData& rhs)
99 : name(rhs.name),
100 process_name(rhs.process_name),
101 processes(rhs.processes) {
102}
103
104ProcessData::~ProcessData() {}
105
106ProcessData& ProcessData::operator=(const ProcessData& rhs) {
107 name = rhs.name;
108 process_name = rhs.process_name;
109 processes = rhs.processes;
110 return *this;
111}
112
initial.commit09911bf2008-07-26 23:55:29113// About threading:
114//
115// This operation will hit no fewer than 3 threads.
116//
[email protected]8be45842012-04-13 19:49:29117// The BrowserChildProcessHostIterator can only be accessed from the IO thread.
initial.commit09911bf2008-07-26 23:55:29118//
119// The RenderProcessHostIterator can only be accessed from the UI thread.
120//
121// This operation can take 30-100ms to complete. We never want to have
122// one task run for that long on the UI or IO threads. So, we run the
123// expensive parts of this operation over on the file thread.
124//
[email protected]4306df72012-04-20 18:58:57125void MemoryDetails::StartFetch(UserMetricsMode user_metrics_mode) {
[email protected]9bb480ee2011-08-03 21:41:16126 // This might get called from the UI or FILE threads, but should not be
127 // getting called from the IO thread.
[email protected]f8b3ef82010-10-11 02:45:52128 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4306df72012-04-20 18:58:57129 user_metrics_mode_ = user_metrics_mode;
initial.commit09911bf2008-07-26 23:55:29130
131 // In order to process this request, we need to use the plugin information.
132 // However, plugin process information is only available from the IO thread.
[email protected]f8b3ef82010-10-11 02:45:52133 BrowserThread::PostTask(
134 BrowserThread::IO, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51135 base::Bind(&MemoryDetails::CollectChildInfoOnIOThread, this));
initial.commit09911bf2008-07-26 23:55:29136}
137
[email protected]8e383412010-10-19 16:57:03138MemoryDetails::~MemoryDetails() {}
139
[email protected]4306df72012-04-20 18:58:57140std::string MemoryDetails::ToLogString() {
141 std::string log;
142 log.reserve(4096);
[email protected]8e23c882012-05-05 01:14:11143 ProcessMemoryInformationList processes = ChromeBrowser()->processes;
144 // Sort by memory consumption, low to high.
145 std::sort(processes.begin(), processes.end());
146 // Print from high to low.
147 for (ProcessMemoryInformationList::reverse_iterator iter1 =
148 processes.rbegin();
149 iter1 != processes.rend();
150 ++iter1) {
[email protected]4306df72012-04-20 18:58:57151 log += ProcessMemoryInformation::GetFullTypeNameInEnglish(
[email protected]f3b357692013-03-22 05:16:13152 iter1->process_type, iter1->renderer_type);
[email protected]4306df72012-04-20 18:58:57153 if (!iter1->titles.empty()) {
154 log += " [";
155 for (std::vector<string16>::const_iterator iter2 =
156 iter1->titles.begin();
157 iter2 != iter1->titles.end(); ++iter2) {
158 if (iter2 != iter1->titles.begin())
159 log += "|";
160 log += UTF16ToUTF8(*iter2);
161 }
162 log += "]";
163 }
[email protected]aa1255b2013-07-31 22:03:09164 log += StringPrintf(" %d MB private, %d MB shared",
[email protected]4306df72012-04-20 18:58:57165 static_cast<int>(iter1->working_set.priv) / 1024,
166 static_cast<int>(iter1->working_set.shared) / 1024);
[email protected]aa1255b2013-07-31 22:03:09167#if defined(OS_CHROMEOS)
168 log += StringPrintf(", %d MB swapped",
169 static_cast<int>(iter1->working_set.swapped) / 1024);
170#endif
171 log += "\n";
[email protected]4306df72012-04-20 18:58:57172 }
173 return log;
174}
175
[email protected]a27a9382009-02-11 23:55:10176void MemoryDetails::CollectChildInfoOnIOThread() {
[email protected]f8b3ef82010-10-11 02:45:52177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29178
[email protected]a27a9382009-02-11 23:55:10179 std::vector<ProcessMemoryInformation> child_info;
180
[email protected]82a14c12012-11-13 18:40:55181 // Collect the list of child processes. A 0 |handle| means that
182 // the process is being launched, so we skip it.
[email protected]4967f792012-01-20 22:14:40183 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]a27a9382009-02-11 23:55:10184 ProcessMemoryInformation info;
[email protected]82a14c12012-11-13 18:40:55185 if (!iter.GetData().handle)
186 continue;
[email protected]4967f792012-01-20 22:14:40187 info.pid = base::GetProcId(iter.GetData().handle);
[email protected]a27a9382009-02-11 23:55:10188 if (!info.pid)
189 continue;
190
[email protected]f3b357692013-03-22 05:16:13191 info.process_type = iter.GetData().process_type;
[email protected]2c1978a2011-11-29 17:02:39192 info.renderer_type = ProcessMemoryInformation::RENDERER_UNKNOWN;
[email protected]4967f792012-01-20 22:14:40193 info.titles.push_back(iter.GetData().name);
[email protected]a27a9382009-02-11 23:55:10194 child_info.push_back(info);
initial.commit09911bf2008-07-26 23:55:29195 }
196
197 // Now go do expensive memory lookups from the file thread.
[email protected]f8b3ef82010-10-11 02:45:52198 BrowserThread::PostTask(
199 BrowserThread::FILE, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51200 base::Bind(&MemoryDetails::CollectProcessData, this, child_info));
initial.commit09911bf2008-07-26 23:55:29201}
202
[email protected]a27a9382009-02-11 23:55:10203void MemoryDetails::CollectChildInfoOnUIThread() {
[email protected]f8b3ef82010-10-11 02:45:52204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
initial.commit09911bf2008-07-26 23:55:29205
[email protected]a423c9e2012-03-06 18:02:31206#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]c2c68b1f2012-02-25 00:29:15207 const pid_t zygote_pid = content::ZygoteHost::GetInstance()->GetPid();
[email protected]52356d22012-02-29 18:34:20208 const pid_t sandbox_helper_pid =
209 content::ZygoteHost::GetInstance()->GetSandboxHelperPid();
[email protected]54fd1d32009-09-01 00:12:58210#endif
211
212 ProcessData* const chrome_browser = ChromeBrowser();
[email protected]a27a9382009-02-11 23:55:10213 // Get more information about the process.
[email protected]54fd1d32009-09-01 00:12:58214 for (size_t index = 0; index < chrome_browser->processes.size();
initial.commit09911bf2008-07-26 23:55:29215 index++) {
[email protected]a27a9382009-02-11 23:55:10216 // Check if it's a renderer, if so get the list of page titles in it and
[email protected]fcf79352010-12-28 20:13:20217 // check if it's a diagnostics-related process. We skip about:memory pages.
218 // Iterate the RenderProcessHosts to find the tab contents.
[email protected]54fd1d32009-09-01 00:12:58219 ProcessMemoryInformation& process =
220 chrome_browser->processes[index];
221
[email protected]a801cb32013-09-11 18:02:27222 scoped_ptr<content::RenderWidgetHostIterator> widgets(
223 RenderWidgetHost::GetRenderWidgetHosts());
224 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
[email protected]f3b1a082011-11-18 00:34:30225 content::RenderProcessHost* render_process_host =
[email protected]a801cb32013-09-11 18:02:27226 widget->GetProcess();
[email protected]fcf79352010-12-28 20:13:20227 DCHECK(render_process_host);
[email protected]8a34e6602010-10-02 17:29:43228 // Ignore processes that don't have a connection, such as crashed tabs.
[email protected]fcf79352010-12-28 20:13:20229 if (!render_process_host->HasConnection() ||
230 process.pid != base::GetProcId(render_process_host->GetHandle())) {
[email protected]a27a9382009-02-11 23:55:10231 continue;
[email protected]201b2732009-11-13 18:57:46232 }
[email protected]f3b357692013-03-22 05:16:13233 process.process_type = content::PROCESS_TYPE_RENDERER;
[email protected]9b62ecf2011-07-27 20:23:08234 Profile* profile =
[email protected]f3b1a082011-11-18 00:34:30235 Profile::FromBrowserContext(
236 render_process_host->GetBrowserContext());
[email protected]79dc42cd2011-01-08 21:43:35237 ExtensionService* extension_service = profile->GetExtensionService();
[email protected]267b4932012-10-11 18:04:26238 extensions::ProcessMap* extension_process_map = NULL;
239 // No extensions on Android. So extension_service can be NULL.
240 if (extension_service)
241 extension_process_map = extension_service->process_map();
[email protected]79dc42cd2011-01-08 21:43:35242
[email protected]0932b30c2012-04-17 13:25:10243 // The RenderProcessHost may host multiple WebContentses. Any
[email protected]a27a9382009-02-11 23:55:10244 // of them which contain diagnostics information make the whole
245 // process be considered a diagnostics process.
[email protected]a801cb32013-09-11 18:02:27246 if (!widget->IsRenderView())
[email protected]039b84a42013-06-21 20:23:37247 continue;
initial.commit09911bf2008-07-26 23:55:29248
[email protected]a801cb32013-09-11 18:02:27249 RenderViewHost* host = RenderViewHost::From(widget);
[email protected]039b84a42013-06-21 20:23:37250 WebContents* contents = WebContents::FromRenderViewHost(host);
251 GURL url;
252 if (contents) {
253 url = contents->GetURL();
254 SiteData* site_data =
255 &chrome_browser->site_data[contents->GetBrowserContext()];
256 SiteDetails::CollectSiteInfo(contents, site_data);
257 }
258 extensions::ViewType type = extensions::GetViewType(contents);
259 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
260 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
261 } else if (extension_process_map &&
262 extension_process_map->Contains(host->GetProcess()->GetID())) {
263 // For our purposes, don't count processes containing only hosted apps
264 // as extension processes. See also: crbug.com/102533.
265 std::set<std::string> extension_ids =
266 extension_process_map->GetExtensionsInProcess(
267 host->GetProcess()->GetID());
268 for (std::set<std::string>::iterator iter = extension_ids.begin();
269 iter != extension_ids.end(); ++iter) {
[email protected]299d7f12012-05-23 05:31:15270 const Extension* extension =
[email protected]039b84a42013-06-21 20:23:37271 extension_service->GetExtensionById(*iter, false);
272 if (extension && !extension->is_hosted_app()) {
[email protected]04d9cc402012-08-17 22:30:12273 process.renderer_type =
274 ProcessMemoryInformation::RENDERER_EXTENSION;
[email protected]039b84a42013-06-21 20:23:37275 break;
[email protected]fcf79352010-12-28 20:13:20276 }
[email protected]fcf79352010-12-28 20:13:20277 }
[email protected]039b84a42013-06-21 20:23:37278 }
279 if (extension_process_map &&
280 extension_process_map->Contains(host->GetProcess()->GetID())) {
281 const Extension* extension =
282 extension_service->extensions()->GetByID(url.host());
283 if (extension) {
284 string16 title = UTF8ToUTF16(extension->name());
285 process.titles.push_back(title);
[email protected]299d7f12012-05-23 05:31:15286 process.renderer_type =
[email protected]039b84a42013-06-21 20:23:37287 ProcessMemoryInformation::RENDERER_EXTENSION;
[email protected]299d7f12012-05-23 05:31:15288 continue;
289 }
[email protected]039b84a42013-06-21 20:23:37290 }
[email protected]299d7f12012-05-23 05:31:15291
[email protected]039b84a42013-06-21 20:23:37292 if (!contents) {
293 process.renderer_type =
294 ProcessMemoryInformation::RENDERER_INTERSTITIAL;
295 continue;
296 }
[email protected]299d7f12012-05-23 05:31:15297
[email protected]039b84a42013-06-21 20:23:37298 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
299 process.titles.push_back(UTF8ToUTF16(url.spec()));
300 process.renderer_type =
301 ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
302 continue;
303 }
[email protected]299d7f12012-05-23 05:31:15304
[email protected]039b84a42013-06-21 20:23:37305 if (type == extensions::VIEW_TYPE_NOTIFICATION) {
306 process.titles.push_back(UTF8ToUTF16(url.spec()));
307 process.renderer_type =
308 ProcessMemoryInformation::RENDERER_NOTIFICATION;
309 continue;
310 }
[email protected]fcf79352010-12-28 20:13:20311
[email protected]039b84a42013-06-21 20:23:37312 // Since we have a WebContents and and the renderer type hasn't been
313 // set yet, it must be a normal tabbed renderer.
314 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
315 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
[email protected]cd3d7892009-03-04 23:55:06316
[email protected]039b84a42013-06-21 20:23:37317 string16 title = contents->GetTitle();
318 if (!title.length())
319 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
320 process.titles.push_back(title);
321
322 // We need to check the pending entry as well as the virtual_url to
323 // see if it's a chrome://memory URL (we don't want to count these in
324 // the total memory usage of the browser).
325 //
326 // When we reach here, chrome://memory will be the pending entry since
327 // we haven't responded with any data such that it would be committed.
328 // If you have another chrome://memory tab open (which would be
329 // committed), we don't want to count it either, so we also check the
330 // last committed entry.
331 //
332 // Either the pending or last committed entries can be NULL.
333 const NavigationEntry* pending_entry =
334 contents->GetController().GetPendingEntry();
335 const NavigationEntry* last_committed_entry =
336 contents->GetController().GetLastCommittedEntry();
337 if ((last_committed_entry &&
338 LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(),
339 chrome::kChromeUIMemoryURL)) ||
340 (pending_entry &&
341 LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(),
342 chrome::kChromeUIMemoryURL))) {
343 process.is_diagnostics = true;
initial.commit09911bf2008-07-26 23:55:29344 }
345 }
[email protected]54fd1d32009-09-01 00:12:58346
[email protected]a423c9e2012-03-06 18:02:31347#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]54fd1d32009-09-01 00:12:58348 if (process.pid == zygote_pid) {
[email protected]f3b357692013-03-22 05:16:13349 process.process_type = content::PROCESS_TYPE_ZYGOTE;
[email protected]54fd1d32009-09-01 00:12:58350 } else if (process.pid == sandbox_helper_pid) {
[email protected]f3b357692013-03-22 05:16:13351 process.process_type = content::PROCESS_TYPE_SANDBOX_HELPER;
[email protected]54fd1d32009-09-01 00:12:58352 }
353#endif
initial.commit09911bf2008-07-26 23:55:29354 }
355
[email protected]a27a9382009-02-11 23:55:10356 // Get rid of other Chrome processes that are from a different profile.
[email protected]54fd1d32009-09-01 00:12:58357 for (size_t index = 0; index < chrome_browser->processes.size();
[email protected]a27a9382009-02-11 23:55:10358 index++) {
[email protected]f3b357692013-03-22 05:16:13359 if (chrome_browser->processes[index].process_type ==
[email protected]bd5d6cf2011-12-01 00:39:12360 content::PROCESS_TYPE_UNKNOWN) {
[email protected]54fd1d32009-09-01 00:12:58361 chrome_browser->processes.erase(
362 chrome_browser->processes.begin() + index);
[email protected]a436d922009-02-13 23:16:42363 index--;
[email protected]a27a9382009-02-11 23:55:10364 }
365 }
366
[email protected]4306df72012-04-20 18:58:57367 if (user_metrics_mode_ == UPDATE_USER_METRICS)
368 UpdateHistograms();
initial.commit09911bf2008-07-26 23:55:29369
370 OnDetailsAvailable();
371}
372
373void MemoryDetails::UpdateHistograms() {
374 // Reports a set of memory metrics to UMA.
[email protected]57c4b852009-08-17 21:59:29375 // Memory is measured in KB.
initial.commit09911bf2008-07-26 23:55:29376
[email protected]54fd1d32009-09-01 00:12:58377 const ProcessData& browser = *ChromeBrowser();
initial.commit09911bf2008-07-26 23:55:29378 size_t aggregate_memory = 0;
[email protected]fcf79352010-12-28 20:13:20379 int chrome_count = 0;
380 int extension_count = 0;
[email protected]a27a9382009-02-11 23:55:10381 int plugin_count = 0;
[email protected]eef348fb2011-08-01 21:11:08382 int pepper_plugin_count = 0;
[email protected]3f5f5162012-10-17 09:19:40383 int pepper_plugin_broker_count = 0;
[email protected]fcf79352010-12-28 20:13:20384 int renderer_count = 0;
385 int other_count = 0;
[email protected]a27a9382009-02-11 23:55:10386 int worker_count = 0;
[email protected]1ae93fb12013-06-14 03:38:56387 int process_limit = content::RenderProcessHost::GetMaxRendererProcessCount();
initial.commit09911bf2008-07-26 23:55:29388 for (size_t index = 0; index < browser.processes.size(); index++) {
[email protected]921cd0cc2008-10-21 22:30:55389 int sample = static_cast<int>(browser.processes[index].working_set.priv);
390 aggregate_memory += sample;
[email protected]f3b357692013-03-22 05:16:13391 switch (browser.processes[index].process_type) {
[email protected]bd5d6cf2011-12-01 00:39:12392 case content::PROCESS_TYPE_BROWSER:
[email protected]f164cea2009-11-05 23:37:40393 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
[email protected]23deabb72013-07-16 21:55:20394 continue;
[email protected]bd5d6cf2011-12-01 00:39:12395 case content::PROCESS_TYPE_RENDERER: {
[email protected]2c1978a2011-11-29 17:02:39396 ProcessMemoryInformation::RendererProcessType renderer_type =
[email protected]fcf79352010-12-28 20:13:20397 browser.processes[index].renderer_type;
398 switch (renderer_type) {
[email protected]2c1978a2011-11-29 17:02:39399 case ProcessMemoryInformation::RENDERER_EXTENSION:
[email protected]fcf79352010-12-28 20:13:20400 UMA_HISTOGRAM_MEMORY_KB("Memory.Extension", sample);
401 extension_count++;
[email protected]23deabb72013-07-16 21:55:20402 continue;
[email protected]2c1978a2011-11-29 17:02:39403 case ProcessMemoryInformation::RENDERER_CHROME:
[email protected]fcf79352010-12-28 20:13:20404 UMA_HISTOGRAM_MEMORY_KB("Memory.Chrome", sample);
405 chrome_count++;
[email protected]23deabb72013-07-16 21:55:20406 continue;
[email protected]2c1978a2011-11-29 17:02:39407 case ProcessMemoryInformation::RENDERER_UNKNOWN:
[email protected]fcf79352010-12-28 20:13:20408 NOTREACHED() << "Unknown renderer process type.";
[email protected]23deabb72013-07-16 21:55:20409 continue;
[email protected]2c1978a2011-11-29 17:02:39410 case ProcessMemoryInformation::RENDERER_NORMAL:
[email protected]fcf79352010-12-28 20:13:20411 default:
412 // TODO(erikkay): Should we bother splitting out the other subtypes?
413 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
414 renderer_count++;
[email protected]23deabb72013-07-16 21:55:20415 continue;
[email protected]fcf79352010-12-28 20:13:20416 }
[email protected]fcf79352010-12-28 20:13:20417 }
[email protected]bd5d6cf2011-12-01 00:39:12418 case content::PROCESS_TYPE_PLUGIN:
[email protected]f164cea2009-11-05 23:37:40419 UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
420 plugin_count++;
[email protected]23deabb72013-07-16 21:55:20421 continue;
[email protected]bd5d6cf2011-12-01 00:39:12422 case content::PROCESS_TYPE_WORKER:
[email protected]f164cea2009-11-05 23:37:40423 UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
424 worker_count++;
[email protected]23deabb72013-07-16 21:55:20425 continue;
[email protected]bd5d6cf2011-12-01 00:39:12426 case content::PROCESS_TYPE_UTILITY:
[email protected]f164cea2009-11-05 23:37:40427 UMA_HISTOGRAM_MEMORY_KB("Memory.Utility", sample);
[email protected]fcf79352010-12-28 20:13:20428 other_count++;
[email protected]23deabb72013-07-16 21:55:20429 continue;
[email protected]bd5d6cf2011-12-01 00:39:12430 case content::PROCESS_TYPE_ZYGOTE:
[email protected]f164cea2009-11-05 23:37:40431 UMA_HISTOGRAM_MEMORY_KB("Memory.Zygote", sample);
[email protected]fcf79352010-12-28 20:13:20432 other_count++;
[email protected]23deabb72013-07-16 21:55:20433 continue;
[email protected]bd5d6cf2011-12-01 00:39:12434 case content::PROCESS_TYPE_SANDBOX_HELPER:
[email protected]f164cea2009-11-05 23:37:40435 UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample);
[email protected]fcf79352010-12-28 20:13:20436 other_count++;
[email protected]23deabb72013-07-16 21:55:20437 continue;
[email protected]bd5d6cf2011-12-01 00:39:12438 case content::PROCESS_TYPE_GPU:
[email protected]96fcbf2d2010-08-03 16:10:27439 UMA_HISTOGRAM_MEMORY_KB("Memory.Gpu", sample);
[email protected]fcf79352010-12-28 20:13:20440 other_count++;
[email protected]23deabb72013-07-16 21:55:20441 continue;
[email protected]bd5d6cf2011-12-01 00:39:12442 case content::PROCESS_TYPE_PPAPI_PLUGIN:
[email protected]eef348fb2011-08-01 21:11:08443 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPlugin", sample);
444 pepper_plugin_count++;
[email protected]23deabb72013-07-16 21:55:20445 continue;
[email protected]3f5f5162012-10-17 09:19:40446 case content::PROCESS_TYPE_PPAPI_BROKER:
447 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPluginBroker", sample);
448 pepper_plugin_broker_count++;
[email protected]23deabb72013-07-16 21:55:20449 continue;
[email protected]f3b357692013-03-22 05:16:13450 case PROCESS_TYPE_NACL_LOADER:
451 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample);
452 other_count++;
[email protected]23deabb72013-07-16 21:55:20453 continue;
[email protected]f3b357692013-03-22 05:16:13454 case PROCESS_TYPE_NACL_BROKER:
455 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClientBroker", sample);
456 other_count++;
[email protected]23deabb72013-07-16 21:55:20457 continue;
[email protected]f164cea2009-11-05 23:37:40458 default:
459 NOTREACHED();
[email protected]23deabb72013-07-16 21:55:20460 continue;
initial.commit09911bf2008-07-26 23:55:29461 }
462 }
[email protected]57c4b852009-08-17 21:59:29463 UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore",
[email protected]0b07be452012-02-29 01:14:42464 RenderWidgetHost::BackingStoreMemorySize() / 1024);
[email protected]dc0b5bd2012-12-11 21:24:39465#if defined(OS_CHROMEOS)
466 // Chrome OS exposes system-wide graphics driver memory which has historically
467 // been a source of leak/bloat.
468 base::SystemMemoryInfoKB meminfo;
469 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1)
470 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
471#endif
[email protected]a27a9382009-02-11 23:55:10472
[email protected]1ae93fb12013-06-14 03:38:56473 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
[email protected]553dba62009-02-24 19:08:23474 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
initial.commit09911bf2008-07-26 23:55:29475 static_cast<int>(browser.processes.size()));
[email protected]fcf79352010-12-28 20:13:20476 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
477 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
478 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
[email protected]553dba62009-02-24 19:08:23479 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
[email protected]eef348fb2011-08-01 21:11:08480 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
481 pepper_plugin_count);
[email protected]3f5f5162012-10-17 09:19:40482 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
483 pepper_plugin_broker_count);
[email protected]fcf79352010-12-28 20:13:20484 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
[email protected]553dba62009-02-24 19:08:23485 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
[email protected]f164cea2009-11-05 23:37:40486 // TODO(viettrungluu): Do we want separate counts for the other
487 // (platform-specific) process types?
[email protected]921cd0cc2008-10-21 22:30:55488
489 int total_sample = static_cast<int>(aggregate_memory / 1000);
[email protected]553dba62009-02-24 19:08:23490 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
[email protected]1ae93fb12013-06-14 03:38:56491
492 // Predict the number of processes needed when isolating all sites and when
493 // isolating only HTTPS sites.
494 int all_renderer_count = renderer_count + chrome_count + extension_count;
495 int non_renderer_count = browser.processes.size() - all_renderer_count;
496 SiteDetails::UpdateHistograms(browser.site_data, all_renderer_count,
497 non_renderer_count);
[email protected]23deabb72013-07-16 21:55:20498#if defined(OS_CHROMEOS)
499 UpdateSwapHistograms();
500#endif
501
initial.commit09911bf2008-07-26 23:55:29502}
[email protected]23deabb72013-07-16 21:55:20503
504#if defined(OS_CHROMEOS)
505void MemoryDetails::UpdateSwapHistograms() {
[email protected]f4134782013-08-29 21:25:20506 UMA_HISTOGRAM_BOOLEAN("Memory.Swap.HaveSwapped", swap_info_.num_writes > 0);
507 if (swap_info_.num_writes == 0)
[email protected]48e303442013-07-18 19:13:15508 return;
509
510 // Only record swap info when any swaps have happened, to give us more
511 // detail in the histograms.
[email protected]23deabb72013-07-16 21:55:20512 const ProcessData& browser = *ChromeBrowser();
513 size_t aggregate_memory = 0;
514 for (size_t index = 0; index < browser.processes.size(); index++) {
515 int sample = static_cast<int>(browser.processes[index].working_set.swapped);
516 aggregate_memory += sample;
517 switch (browser.processes[index].process_type) {
518 case content::PROCESS_TYPE_BROWSER:
519 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Browser", sample);
520 continue;
521 case content::PROCESS_TYPE_RENDERER: {
522 ProcessMemoryInformation::RendererProcessType renderer_type =
523 browser.processes[index].renderer_type;
524 switch (renderer_type) {
525 case ProcessMemoryInformation::RENDERER_EXTENSION:
526 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Extension", sample);
527 continue;
528 case ProcessMemoryInformation::RENDERER_CHROME:
529 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Chrome", sample);
530 continue;
531 case ProcessMemoryInformation::RENDERER_UNKNOWN:
532 NOTREACHED() << "Unknown renderer process type.";
533 continue;
534 case ProcessMemoryInformation::RENDERER_NORMAL:
535 default:
536 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Renderer", sample);
537 continue;
538 }
539 }
540 case content::PROCESS_TYPE_PLUGIN:
541 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Plugin", sample);
542 continue;
543 case content::PROCESS_TYPE_WORKER:
544 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Worker", sample);
545 continue;
546 case content::PROCESS_TYPE_UTILITY:
547 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Utility", sample);
548 continue;
549 case content::PROCESS_TYPE_ZYGOTE:
550 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Zygote", sample);
551 continue;
552 case content::PROCESS_TYPE_SANDBOX_HELPER:
553 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.SandboxHelper", sample);
554 continue;
555 case content::PROCESS_TYPE_GPU:
556 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Gpu", sample);
557 continue;
558 case content::PROCESS_TYPE_PPAPI_PLUGIN:
559 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPlugin", sample);
560 continue;
561 case content::PROCESS_TYPE_PPAPI_BROKER:
562 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPluginBroker", sample);
563 continue;
564 case PROCESS_TYPE_NACL_LOADER:
565 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClient", sample);
566 continue;
567 case PROCESS_TYPE_NACL_BROKER:
568 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClientBroker", sample);
569 continue;
570 default:
571 NOTREACHED();
572 continue;
573 }
574 }
575
576 int total_sample = static_cast<int>(aggregate_memory / 1000);
577 UMA_HISTOGRAM_MEMORY_MB("Memory.Swap.Total", total_sample);
[email protected]48e303442013-07-18 19:13:15578
579 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.CompressedDataSize",
[email protected]f4134782013-08-29 21:25:20580 swap_info_.compr_data_size / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15581 1, 4096, 50);
582 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.OriginalDataSize",
[email protected]f4134782013-08-29 21:25:20583 swap_info_.orig_data_size / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15584 1, 4096, 50);
585 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.MemUsedTotal",
[email protected]f4134782013-08-29 21:25:20586 swap_info_.mem_used_total / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15587 1, 4096, 50);
[email protected]aa1255b2013-07-31 22:03:09588 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumReads",
[email protected]f4134782013-08-29 21:25:20589 swap_info_.num_reads,
[email protected]aa1255b2013-07-31 22:03:09590 1, 100000000, 100);
591 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumWrites",
[email protected]f4134782013-08-29 21:25:20592 swap_info_.num_writes,
[email protected]aa1255b2013-07-31 22:03:09593 1, 100000000, 100);
[email protected]48e303442013-07-18 19:13:15594
[email protected]f4134782013-08-29 21:25:20595 if (swap_info_.orig_data_size > 0 && swap_info_.compr_data_size > 0) {
[email protected]48e303442013-07-18 19:13:15596 UMA_HISTOGRAM_CUSTOM_COUNTS(
597 "Memory.Swap.CompressionRatio",
[email protected]f4134782013-08-29 21:25:20598 swap_info_.orig_data_size / swap_info_.compr_data_size,
[email protected]48e303442013-07-18 19:13:15599 1, 20, 20);
600 }
[email protected]23deabb72013-07-16 21:55:20601}
602
603#endif