blob: 643e211a6845e440d980ab162e6df8605918b3d7 [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]83ff91c2012-01-05 20:54:1326#include "content/public/browser/web_contents.h"
[email protected]e091df82011-10-11 18:13:2127#include "content/public/common/bindings_policy.h"
[email protected]cb2edf22013-04-01 20:25:2328#include "extensions/browser/view_type_utils.h"
[email protected]ae5ca892009-07-30 18:00:4729#include "grit/chromium_strings.h"
[email protected]4f260d02010-12-23 18:35:4230#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1731#include "ui/base/l10n/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2932
[email protected]a423c9e2012-03-06 18:02:3133#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]c2c68b1f2012-02-25 00:29:1534#include "content/public/browser/zygote_host_linux.h"
[email protected]54fd1d32009-09-01 00:12:5835#endif
initial.commit09911bf2008-07-26 23:55:2936
[email protected]4306df72012-04-20 18:58:5737using base::StringPrintf;
[email protected]4967f792012-01-20 22:14:4038using content::BrowserChildProcessHostIterator;
[email protected]631bb742011-11-02 11:29:3939using content::BrowserThread;
[email protected]10f417c52011-12-28 21:04:2340using content::NavigationEntry;
[email protected]eaabba22012-03-07 15:02:1141using content::RenderViewHost;
42using content::RenderWidgetHost;
[email protected]83ff91c2012-01-05 20:54:1343using content::WebContents;
[email protected]1c321ee2012-05-21 03:02:3444using extensions::Extension;
[email protected]631bb742011-11-02 11:29:3945
[email protected]2c1978a2011-11-29 17:02:3946// static
47std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish(
48 RendererProcessType type) {
49 switch (type) {
50 case RENDERER_NORMAL:
51 return "Tab";
52 case RENDERER_CHROME:
53 return "Tab (Chrome)";
54 case RENDERER_EXTENSION:
55 return "Extension";
56 case RENDERER_DEVTOOLS:
57 return "Devtools";
58 case RENDERER_INTERSTITIAL:
59 return "Interstitial";
60 case RENDERER_NOTIFICATION:
61 return "Notification";
62 case RENDERER_BACKGROUND_APP:
63 return "Background App";
64 case RENDERER_UNKNOWN:
65 default:
66 NOTREACHED() << "Unknown renderer process type!";
67 return "Unknown";
68 }
69}
70
71// static
72std::string ProcessMemoryInformation::GetFullTypeNameInEnglish(
[email protected]f3b357692013-03-22 05:16:1373 int process_type,
[email protected]2c1978a2011-11-29 17:02:3974 RendererProcessType rtype) {
[email protected]f3b357692013-03-22 05:16:1375 if (process_type == content::PROCESS_TYPE_RENDERER)
[email protected]2c1978a2011-11-29 17:02:3976 return GetRendererTypeNameInEnglish(rtype);
[email protected]f3b357692013-03-22 05:16:1377 return content::GetProcessTypeNameInEnglish(process_type);
[email protected]2c1978a2011-11-29 17:02:3978}
79
[email protected]8e383412010-10-19 16:57:0380ProcessMemoryInformation::ProcessMemoryInformation()
81 : pid(0),
82 num_processes(0),
83 is_diagnostics(false),
[email protected]f3b357692013-03-22 05:16:1384 process_type(content::PROCESS_TYPE_UNKNOWN),
[email protected]2c1978a2011-11-29 17:02:3985 renderer_type(RENDERER_UNKNOWN) {
[email protected]8e383412010-10-19 16:57:0386}
87
88ProcessMemoryInformation::~ProcessMemoryInformation() {}
89
[email protected]8e23c882012-05-05 01:14:1190bool ProcessMemoryInformation::operator<(
91 const ProcessMemoryInformation& rhs) const {
92 return working_set.priv < rhs.working_set.priv;
93}
94
[email protected]93aa89c72010-10-20 21:32:0495ProcessData::ProcessData() {}
96
97ProcessData::ProcessData(const ProcessData& rhs)
98 : name(rhs.name),
99 process_name(rhs.process_name),
100 processes(rhs.processes) {
101}
102
103ProcessData::~ProcessData() {}
104
105ProcessData& ProcessData::operator=(const ProcessData& rhs) {
106 name = rhs.name;
107 process_name = rhs.process_name;
108 processes = rhs.processes;
109 return *this;
110}
111
initial.commit09911bf2008-07-26 23:55:29112// About threading:
113//
114// This operation will hit no fewer than 3 threads.
115//
[email protected]8be45842012-04-13 19:49:29116// The BrowserChildProcessHostIterator can only be accessed from the IO thread.
initial.commit09911bf2008-07-26 23:55:29117//
118// The RenderProcessHostIterator can only be accessed from the UI thread.
119//
120// This operation can take 30-100ms to complete. We never want to have
121// one task run for that long on the UI or IO threads. So, we run the
122// expensive parts of this operation over on the file thread.
123//
[email protected]4306df72012-04-20 18:58:57124void MemoryDetails::StartFetch(UserMetricsMode user_metrics_mode) {
[email protected]9bb480ee2011-08-03 21:41:16125 // This might get called from the UI or FILE threads, but should not be
126 // getting called from the IO thread.
[email protected]f8b3ef82010-10-11 02:45:52127 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4306df72012-04-20 18:58:57128 user_metrics_mode_ = user_metrics_mode;
initial.commit09911bf2008-07-26 23:55:29129
130 // In order to process this request, we need to use the plugin information.
131 // However, plugin process information is only available from the IO thread.
[email protected]f8b3ef82010-10-11 02:45:52132 BrowserThread::PostTask(
133 BrowserThread::IO, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51134 base::Bind(&MemoryDetails::CollectChildInfoOnIOThread, this));
initial.commit09911bf2008-07-26 23:55:29135}
136
[email protected]8e383412010-10-19 16:57:03137MemoryDetails::~MemoryDetails() {}
138
[email protected]4306df72012-04-20 18:58:57139std::string MemoryDetails::ToLogString() {
140 std::string log;
141 log.reserve(4096);
[email protected]8e23c882012-05-05 01:14:11142 ProcessMemoryInformationList processes = ChromeBrowser()->processes;
143 // Sort by memory consumption, low to high.
144 std::sort(processes.begin(), processes.end());
145 // Print from high to low.
146 for (ProcessMemoryInformationList::reverse_iterator iter1 =
147 processes.rbegin();
148 iter1 != processes.rend();
149 ++iter1) {
[email protected]4306df72012-04-20 18:58:57150 log += ProcessMemoryInformation::GetFullTypeNameInEnglish(
[email protected]f3b357692013-03-22 05:16:13151 iter1->process_type, iter1->renderer_type);
[email protected]4306df72012-04-20 18:58:57152 if (!iter1->titles.empty()) {
153 log += " [";
154 for (std::vector<string16>::const_iterator iter2 =
155 iter1->titles.begin();
156 iter2 != iter1->titles.end(); ++iter2) {
157 if (iter2 != iter1->titles.begin())
158 log += "|";
159 log += UTF16ToUTF8(*iter2);
160 }
161 log += "]";
162 }
[email protected]aa1255b2013-07-31 22:03:09163 log += StringPrintf(" %d MB private, %d MB shared",
[email protected]4306df72012-04-20 18:58:57164 static_cast<int>(iter1->working_set.priv) / 1024,
165 static_cast<int>(iter1->working_set.shared) / 1024);
[email protected]aa1255b2013-07-31 22:03:09166#if defined(OS_CHROMEOS)
167 log += StringPrintf(", %d MB swapped",
168 static_cast<int>(iter1->working_set.swapped) / 1024);
169#endif
170 log += "\n";
[email protected]4306df72012-04-20 18:58:57171 }
172 return log;
173}
174
[email protected]a27a9382009-02-11 23:55:10175void MemoryDetails::CollectChildInfoOnIOThread() {
[email protected]f8b3ef82010-10-11 02:45:52176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29177
[email protected]a27a9382009-02-11 23:55:10178 std::vector<ProcessMemoryInformation> child_info;
179
[email protected]82a14c12012-11-13 18:40:55180 // Collect the list of child processes. A 0 |handle| means that
181 // the process is being launched, so we skip it.
[email protected]4967f792012-01-20 22:14:40182 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]a27a9382009-02-11 23:55:10183 ProcessMemoryInformation info;
[email protected]82a14c12012-11-13 18:40:55184 if (!iter.GetData().handle)
185 continue;
[email protected]4967f792012-01-20 22:14:40186 info.pid = base::GetProcId(iter.GetData().handle);
[email protected]a27a9382009-02-11 23:55:10187 if (!info.pid)
188 continue;
189
[email protected]f3b357692013-03-22 05:16:13190 info.process_type = iter.GetData().process_type;
[email protected]2c1978a2011-11-29 17:02:39191 info.renderer_type = ProcessMemoryInformation::RENDERER_UNKNOWN;
[email protected]4967f792012-01-20 22:14:40192 info.titles.push_back(iter.GetData().name);
[email protected]a27a9382009-02-11 23:55:10193 child_info.push_back(info);
initial.commit09911bf2008-07-26 23:55:29194 }
195
196 // Now go do expensive memory lookups from the file thread.
[email protected]f8b3ef82010-10-11 02:45:52197 BrowserThread::PostTask(
198 BrowserThread::FILE, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51199 base::Bind(&MemoryDetails::CollectProcessData, this, child_info));
initial.commit09911bf2008-07-26 23:55:29200}
201
[email protected]a27a9382009-02-11 23:55:10202void MemoryDetails::CollectChildInfoOnUIThread() {
[email protected]f8b3ef82010-10-11 02:45:52203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
initial.commit09911bf2008-07-26 23:55:29204
[email protected]a423c9e2012-03-06 18:02:31205#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]c2c68b1f2012-02-25 00:29:15206 const pid_t zygote_pid = content::ZygoteHost::GetInstance()->GetPid();
[email protected]52356d22012-02-29 18:34:20207 const pid_t sandbox_helper_pid =
208 content::ZygoteHost::GetInstance()->GetSandboxHelperPid();
[email protected]54fd1d32009-09-01 00:12:58209#endif
210
211 ProcessData* const chrome_browser = ChromeBrowser();
[email protected]a27a9382009-02-11 23:55:10212 // Get more information about the process.
[email protected]54fd1d32009-09-01 00:12:58213 for (size_t index = 0; index < chrome_browser->processes.size();
initial.commit09911bf2008-07-26 23:55:29214 index++) {
[email protected]a27a9382009-02-11 23:55:10215 // Check if it's a renderer, if so get the list of page titles in it and
[email protected]fcf79352010-12-28 20:13:20216 // check if it's a diagnostics-related process. We skip about:memory pages.
217 // Iterate the RenderProcessHosts to find the tab contents.
[email protected]54fd1d32009-09-01 00:12:58218 ProcessMemoryInformation& process =
219 chrome_browser->processes[index];
220
[email protected]039b84a42013-06-21 20:23:37221 RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
222 for (size_t i = 0; i < widgets.size(); ++i) {
[email protected]f3b1a082011-11-18 00:34:30223 content::RenderProcessHost* render_process_host =
[email protected]039b84a42013-06-21 20:23:37224 widgets[i]->GetProcess();
[email protected]fcf79352010-12-28 20:13:20225 DCHECK(render_process_host);
[email protected]8a34e6602010-10-02 17:29:43226 // Ignore processes that don't have a connection, such as crashed tabs.
[email protected]fcf79352010-12-28 20:13:20227 if (!render_process_host->HasConnection() ||
228 process.pid != base::GetProcId(render_process_host->GetHandle())) {
[email protected]a27a9382009-02-11 23:55:10229 continue;
[email protected]201b2732009-11-13 18:57:46230 }
[email protected]f3b357692013-03-22 05:16:13231 process.process_type = content::PROCESS_TYPE_RENDERER;
[email protected]9b62ecf2011-07-27 20:23:08232 Profile* profile =
[email protected]f3b1a082011-11-18 00:34:30233 Profile::FromBrowserContext(
234 render_process_host->GetBrowserContext());
[email protected]79dc42cd2011-01-08 21:43:35235 ExtensionService* extension_service = profile->GetExtensionService();
[email protected]267b4932012-10-11 18:04:26236 extensions::ProcessMap* extension_process_map = NULL;
237 // No extensions on Android. So extension_service can be NULL.
238 if (extension_service)
239 extension_process_map = extension_service->process_map();
[email protected]79dc42cd2011-01-08 21:43:35240
[email protected]0932b30c2012-04-17 13:25:10241 // The RenderProcessHost may host multiple WebContentses. Any
[email protected]a27a9382009-02-11 23:55:10242 // of them which contain diagnostics information make the whole
243 // process be considered a diagnostics process.
[email protected]039b84a42013-06-21 20:23:37244 if (!widgets[i]->IsRenderView())
245 continue;
initial.commit09911bf2008-07-26 23:55:29246
[email protected]039b84a42013-06-21 20:23:37247 RenderViewHost* host = RenderViewHost::From(widgets[i]);
248 WebContents* contents = WebContents::FromRenderViewHost(host);
249 GURL url;
250 if (contents) {
251 url = contents->GetURL();
252 SiteData* site_data =
253 &chrome_browser->site_data[contents->GetBrowserContext()];
254 SiteDetails::CollectSiteInfo(contents, site_data);
255 }
256 extensions::ViewType type = extensions::GetViewType(contents);
257 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
258 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
259 } else if (extension_process_map &&
260 extension_process_map->Contains(host->GetProcess()->GetID())) {
261 // For our purposes, don't count processes containing only hosted apps
262 // as extension processes. See also: crbug.com/102533.
263 std::set<std::string> extension_ids =
264 extension_process_map->GetExtensionsInProcess(
265 host->GetProcess()->GetID());
266 for (std::set<std::string>::iterator iter = extension_ids.begin();
267 iter != extension_ids.end(); ++iter) {
[email protected]299d7f12012-05-23 05:31:15268 const Extension* extension =
[email protected]039b84a42013-06-21 20:23:37269 extension_service->GetExtensionById(*iter, false);
270 if (extension && !extension->is_hosted_app()) {
[email protected]04d9cc402012-08-17 22:30:12271 process.renderer_type =
272 ProcessMemoryInformation::RENDERER_EXTENSION;
[email protected]039b84a42013-06-21 20:23:37273 break;
[email protected]fcf79352010-12-28 20:13:20274 }
[email protected]fcf79352010-12-28 20:13:20275 }
[email protected]039b84a42013-06-21 20:23:37276 }
277 if (extension_process_map &&
278 extension_process_map->Contains(host->GetProcess()->GetID())) {
279 const Extension* extension =
280 extension_service->extensions()->GetByID(url.host());
281 if (extension) {
282 string16 title = UTF8ToUTF16(extension->name());
283 process.titles.push_back(title);
[email protected]299d7f12012-05-23 05:31:15284 process.renderer_type =
[email protected]039b84a42013-06-21 20:23:37285 ProcessMemoryInformation::RENDERER_EXTENSION;
[email protected]299d7f12012-05-23 05:31:15286 continue;
287 }
[email protected]039b84a42013-06-21 20:23:37288 }
[email protected]299d7f12012-05-23 05:31:15289
[email protected]039b84a42013-06-21 20:23:37290 if (!contents) {
291 process.renderer_type =
292 ProcessMemoryInformation::RENDERER_INTERSTITIAL;
293 continue;
294 }
[email protected]299d7f12012-05-23 05:31:15295
[email protected]039b84a42013-06-21 20:23:37296 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
297 process.titles.push_back(UTF8ToUTF16(url.spec()));
298 process.renderer_type =
299 ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
300 continue;
301 }
[email protected]299d7f12012-05-23 05:31:15302
[email protected]039b84a42013-06-21 20:23:37303 if (type == extensions::VIEW_TYPE_NOTIFICATION) {
304 process.titles.push_back(UTF8ToUTF16(url.spec()));
305 process.renderer_type =
306 ProcessMemoryInformation::RENDERER_NOTIFICATION;
307 continue;
308 }
[email protected]fcf79352010-12-28 20:13:20309
[email protected]039b84a42013-06-21 20:23:37310 // Since we have a WebContents and and the renderer type hasn't been
311 // set yet, it must be a normal tabbed renderer.
312 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
313 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
[email protected]cd3d7892009-03-04 23:55:06314
[email protected]039b84a42013-06-21 20:23:37315 string16 title = contents->GetTitle();
316 if (!title.length())
317 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
318 process.titles.push_back(title);
319
320 // We need to check the pending entry as well as the virtual_url to
321 // see if it's a chrome://memory URL (we don't want to count these in
322 // the total memory usage of the browser).
323 //
324 // When we reach here, chrome://memory will be the pending entry since
325 // we haven't responded with any data such that it would be committed.
326 // If you have another chrome://memory tab open (which would be
327 // committed), we don't want to count it either, so we also check the
328 // last committed entry.
329 //
330 // Either the pending or last committed entries can be NULL.
331 const NavigationEntry* pending_entry =
332 contents->GetController().GetPendingEntry();
333 const NavigationEntry* last_committed_entry =
334 contents->GetController().GetLastCommittedEntry();
335 if ((last_committed_entry &&
336 LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(),
337 chrome::kChromeUIMemoryURL)) ||
338 (pending_entry &&
339 LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(),
340 chrome::kChromeUIMemoryURL))) {
341 process.is_diagnostics = true;
initial.commit09911bf2008-07-26 23:55:29342 }
343 }
[email protected]54fd1d32009-09-01 00:12:58344
[email protected]a423c9e2012-03-06 18:02:31345#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]54fd1d32009-09-01 00:12:58346 if (process.pid == zygote_pid) {
[email protected]f3b357692013-03-22 05:16:13347 process.process_type = content::PROCESS_TYPE_ZYGOTE;
[email protected]54fd1d32009-09-01 00:12:58348 } else if (process.pid == sandbox_helper_pid) {
[email protected]f3b357692013-03-22 05:16:13349 process.process_type = content::PROCESS_TYPE_SANDBOX_HELPER;
[email protected]54fd1d32009-09-01 00:12:58350 }
351#endif
initial.commit09911bf2008-07-26 23:55:29352 }
353
[email protected]a27a9382009-02-11 23:55:10354 // Get rid of other Chrome processes that are from a different profile.
[email protected]54fd1d32009-09-01 00:12:58355 for (size_t index = 0; index < chrome_browser->processes.size();
[email protected]a27a9382009-02-11 23:55:10356 index++) {
[email protected]f3b357692013-03-22 05:16:13357 if (chrome_browser->processes[index].process_type ==
[email protected]bd5d6cf2011-12-01 00:39:12358 content::PROCESS_TYPE_UNKNOWN) {
[email protected]54fd1d32009-09-01 00:12:58359 chrome_browser->processes.erase(
360 chrome_browser->processes.begin() + index);
[email protected]a436d922009-02-13 23:16:42361 index--;
[email protected]a27a9382009-02-11 23:55:10362 }
363 }
364
[email protected]4306df72012-04-20 18:58:57365 if (user_metrics_mode_ == UPDATE_USER_METRICS)
366 UpdateHistograms();
initial.commit09911bf2008-07-26 23:55:29367
368 OnDetailsAvailable();
369}
370
371void MemoryDetails::UpdateHistograms() {
372 // Reports a set of memory metrics to UMA.
[email protected]57c4b852009-08-17 21:59:29373 // Memory is measured in KB.
initial.commit09911bf2008-07-26 23:55:29374
[email protected]54fd1d32009-09-01 00:12:58375 const ProcessData& browser = *ChromeBrowser();
initial.commit09911bf2008-07-26 23:55:29376 size_t aggregate_memory = 0;
[email protected]fcf79352010-12-28 20:13:20377 int chrome_count = 0;
378 int extension_count = 0;
[email protected]a27a9382009-02-11 23:55:10379 int plugin_count = 0;
[email protected]eef348fb2011-08-01 21:11:08380 int pepper_plugin_count = 0;
[email protected]3f5f5162012-10-17 09:19:40381 int pepper_plugin_broker_count = 0;
[email protected]fcf79352010-12-28 20:13:20382 int renderer_count = 0;
383 int other_count = 0;
[email protected]a27a9382009-02-11 23:55:10384 int worker_count = 0;
[email protected]1ae93fb12013-06-14 03:38:56385 int process_limit = content::RenderProcessHost::GetMaxRendererProcessCount();
initial.commit09911bf2008-07-26 23:55:29386 for (size_t index = 0; index < browser.processes.size(); index++) {
[email protected]921cd0cc2008-10-21 22:30:55387 int sample = static_cast<int>(browser.processes[index].working_set.priv);
388 aggregate_memory += sample;
[email protected]f3b357692013-03-22 05:16:13389 switch (browser.processes[index].process_type) {
[email protected]bd5d6cf2011-12-01 00:39:12390 case content::PROCESS_TYPE_BROWSER:
[email protected]f164cea2009-11-05 23:37:40391 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
[email protected]23deabb72013-07-16 21:55:20392 continue;
[email protected]bd5d6cf2011-12-01 00:39:12393 case content::PROCESS_TYPE_RENDERER: {
[email protected]2c1978a2011-11-29 17:02:39394 ProcessMemoryInformation::RendererProcessType renderer_type =
[email protected]fcf79352010-12-28 20:13:20395 browser.processes[index].renderer_type;
396 switch (renderer_type) {
[email protected]2c1978a2011-11-29 17:02:39397 case ProcessMemoryInformation::RENDERER_EXTENSION:
[email protected]fcf79352010-12-28 20:13:20398 UMA_HISTOGRAM_MEMORY_KB("Memory.Extension", sample);
399 extension_count++;
[email protected]23deabb72013-07-16 21:55:20400 continue;
[email protected]2c1978a2011-11-29 17:02:39401 case ProcessMemoryInformation::RENDERER_CHROME:
[email protected]fcf79352010-12-28 20:13:20402 UMA_HISTOGRAM_MEMORY_KB("Memory.Chrome", sample);
403 chrome_count++;
[email protected]23deabb72013-07-16 21:55:20404 continue;
[email protected]2c1978a2011-11-29 17:02:39405 case ProcessMemoryInformation::RENDERER_UNKNOWN:
[email protected]fcf79352010-12-28 20:13:20406 NOTREACHED() << "Unknown renderer process type.";
[email protected]23deabb72013-07-16 21:55:20407 continue;
[email protected]2c1978a2011-11-29 17:02:39408 case ProcessMemoryInformation::RENDERER_NORMAL:
[email protected]fcf79352010-12-28 20:13:20409 default:
410 // TODO(erikkay): Should we bother splitting out the other subtypes?
411 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
412 renderer_count++;
[email protected]23deabb72013-07-16 21:55:20413 continue;
[email protected]fcf79352010-12-28 20:13:20414 }
[email protected]fcf79352010-12-28 20:13:20415 }
[email protected]bd5d6cf2011-12-01 00:39:12416 case content::PROCESS_TYPE_PLUGIN:
[email protected]f164cea2009-11-05 23:37:40417 UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
418 plugin_count++;
[email protected]23deabb72013-07-16 21:55:20419 continue;
[email protected]bd5d6cf2011-12-01 00:39:12420 case content::PROCESS_TYPE_WORKER:
[email protected]f164cea2009-11-05 23:37:40421 UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
422 worker_count++;
[email protected]23deabb72013-07-16 21:55:20423 continue;
[email protected]bd5d6cf2011-12-01 00:39:12424 case content::PROCESS_TYPE_UTILITY:
[email protected]f164cea2009-11-05 23:37:40425 UMA_HISTOGRAM_MEMORY_KB("Memory.Utility", sample);
[email protected]fcf79352010-12-28 20:13:20426 other_count++;
[email protected]23deabb72013-07-16 21:55:20427 continue;
[email protected]bd5d6cf2011-12-01 00:39:12428 case content::PROCESS_TYPE_ZYGOTE:
[email protected]f164cea2009-11-05 23:37:40429 UMA_HISTOGRAM_MEMORY_KB("Memory.Zygote", sample);
[email protected]fcf79352010-12-28 20:13:20430 other_count++;
[email protected]23deabb72013-07-16 21:55:20431 continue;
[email protected]bd5d6cf2011-12-01 00:39:12432 case content::PROCESS_TYPE_SANDBOX_HELPER:
[email protected]f164cea2009-11-05 23:37:40433 UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample);
[email protected]fcf79352010-12-28 20:13:20434 other_count++;
[email protected]23deabb72013-07-16 21:55:20435 continue;
[email protected]bd5d6cf2011-12-01 00:39:12436 case content::PROCESS_TYPE_GPU:
[email protected]96fcbf2d2010-08-03 16:10:27437 UMA_HISTOGRAM_MEMORY_KB("Memory.Gpu", sample);
[email protected]fcf79352010-12-28 20:13:20438 other_count++;
[email protected]23deabb72013-07-16 21:55:20439 continue;
[email protected]bd5d6cf2011-12-01 00:39:12440 case content::PROCESS_TYPE_PPAPI_PLUGIN:
[email protected]eef348fb2011-08-01 21:11:08441 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPlugin", sample);
442 pepper_plugin_count++;
[email protected]23deabb72013-07-16 21:55:20443 continue;
[email protected]3f5f5162012-10-17 09:19:40444 case content::PROCESS_TYPE_PPAPI_BROKER:
445 UMA_HISTOGRAM_MEMORY_KB("Memory.PepperPluginBroker", sample);
446 pepper_plugin_broker_count++;
[email protected]23deabb72013-07-16 21:55:20447 continue;
[email protected]f3b357692013-03-22 05:16:13448 case PROCESS_TYPE_NACL_LOADER:
449 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample);
450 other_count++;
[email protected]23deabb72013-07-16 21:55:20451 continue;
[email protected]f3b357692013-03-22 05:16:13452 case PROCESS_TYPE_NACL_BROKER:
453 UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClientBroker", sample);
454 other_count++;
[email protected]23deabb72013-07-16 21:55:20455 continue;
[email protected]f164cea2009-11-05 23:37:40456 default:
457 NOTREACHED();
[email protected]23deabb72013-07-16 21:55:20458 continue;
initial.commit09911bf2008-07-26 23:55:29459 }
460 }
[email protected]57c4b852009-08-17 21:59:29461 UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore",
[email protected]0b07be452012-02-29 01:14:42462 RenderWidgetHost::BackingStoreMemorySize() / 1024);
[email protected]dc0b5bd2012-12-11 21:24:39463#if defined(OS_CHROMEOS)
464 // Chrome OS exposes system-wide graphics driver memory which has historically
465 // been a source of leak/bloat.
466 base::SystemMemoryInfoKB meminfo;
467 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1)
468 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
469#endif
[email protected]a27a9382009-02-11 23:55:10470
[email protected]1ae93fb12013-06-14 03:38:56471 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
[email protected]553dba62009-02-24 19:08:23472 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
initial.commit09911bf2008-07-26 23:55:29473 static_cast<int>(browser.processes.size()));
[email protected]fcf79352010-12-28 20:13:20474 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
475 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
476 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
[email protected]553dba62009-02-24 19:08:23477 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
[email protected]eef348fb2011-08-01 21:11:08478 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
479 pepper_plugin_count);
[email protected]3f5f5162012-10-17 09:19:40480 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
481 pepper_plugin_broker_count);
[email protected]fcf79352010-12-28 20:13:20482 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
[email protected]553dba62009-02-24 19:08:23483 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
[email protected]f164cea2009-11-05 23:37:40484 // TODO(viettrungluu): Do we want separate counts for the other
485 // (platform-specific) process types?
[email protected]921cd0cc2008-10-21 22:30:55486
487 int total_sample = static_cast<int>(aggregate_memory / 1000);
[email protected]553dba62009-02-24 19:08:23488 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
[email protected]1ae93fb12013-06-14 03:38:56489
490 // Predict the number of processes needed when isolating all sites and when
491 // isolating only HTTPS sites.
492 int all_renderer_count = renderer_count + chrome_count + extension_count;
493 int non_renderer_count = browser.processes.size() - all_renderer_count;
494 SiteDetails::UpdateHistograms(browser.site_data, all_renderer_count,
495 non_renderer_count);
[email protected]23deabb72013-07-16 21:55:20496#if defined(OS_CHROMEOS)
497 UpdateSwapHistograms();
498#endif
499
initial.commit09911bf2008-07-26 23:55:29500}
[email protected]23deabb72013-07-16 21:55:20501
502#if defined(OS_CHROMEOS)
503void MemoryDetails::UpdateSwapHistograms() {
[email protected]f4134782013-08-29 21:25:20504 UMA_HISTOGRAM_BOOLEAN("Memory.Swap.HaveSwapped", swap_info_.num_writes > 0);
505 if (swap_info_.num_writes == 0)
[email protected]48e303442013-07-18 19:13:15506 return;
507
508 // Only record swap info when any swaps have happened, to give us more
509 // detail in the histograms.
[email protected]23deabb72013-07-16 21:55:20510 const ProcessData& browser = *ChromeBrowser();
511 size_t aggregate_memory = 0;
512 for (size_t index = 0; index < browser.processes.size(); index++) {
513 int sample = static_cast<int>(browser.processes[index].working_set.swapped);
514 aggregate_memory += sample;
515 switch (browser.processes[index].process_type) {
516 case content::PROCESS_TYPE_BROWSER:
517 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Browser", sample);
518 continue;
519 case content::PROCESS_TYPE_RENDERER: {
520 ProcessMemoryInformation::RendererProcessType renderer_type =
521 browser.processes[index].renderer_type;
522 switch (renderer_type) {
523 case ProcessMemoryInformation::RENDERER_EXTENSION:
524 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Extension", sample);
525 continue;
526 case ProcessMemoryInformation::RENDERER_CHROME:
527 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Chrome", sample);
528 continue;
529 case ProcessMemoryInformation::RENDERER_UNKNOWN:
530 NOTREACHED() << "Unknown renderer process type.";
531 continue;
532 case ProcessMemoryInformation::RENDERER_NORMAL:
533 default:
534 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Renderer", sample);
535 continue;
536 }
537 }
538 case content::PROCESS_TYPE_PLUGIN:
539 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Plugin", sample);
540 continue;
541 case content::PROCESS_TYPE_WORKER:
542 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Worker", sample);
543 continue;
544 case content::PROCESS_TYPE_UTILITY:
545 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Utility", sample);
546 continue;
547 case content::PROCESS_TYPE_ZYGOTE:
548 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Zygote", sample);
549 continue;
550 case content::PROCESS_TYPE_SANDBOX_HELPER:
551 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.SandboxHelper", sample);
552 continue;
553 case content::PROCESS_TYPE_GPU:
554 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Gpu", sample);
555 continue;
556 case content::PROCESS_TYPE_PPAPI_PLUGIN:
557 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPlugin", sample);
558 continue;
559 case content::PROCESS_TYPE_PPAPI_BROKER:
560 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPluginBroker", sample);
561 continue;
562 case PROCESS_TYPE_NACL_LOADER:
563 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClient", sample);
564 continue;
565 case PROCESS_TYPE_NACL_BROKER:
566 UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClientBroker", sample);
567 continue;
568 default:
569 NOTREACHED();
570 continue;
571 }
572 }
573
574 int total_sample = static_cast<int>(aggregate_memory / 1000);
575 UMA_HISTOGRAM_MEMORY_MB("Memory.Swap.Total", total_sample);
[email protected]48e303442013-07-18 19:13:15576
577 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.CompressedDataSize",
[email protected]f4134782013-08-29 21:25:20578 swap_info_.compr_data_size / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15579 1, 4096, 50);
580 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.OriginalDataSize",
[email protected]f4134782013-08-29 21:25:20581 swap_info_.orig_data_size / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15582 1, 4096, 50);
583 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.MemUsedTotal",
[email protected]f4134782013-08-29 21:25:20584 swap_info_.mem_used_total / (1024 * 1024),
[email protected]48e303442013-07-18 19:13:15585 1, 4096, 50);
[email protected]aa1255b2013-07-31 22:03:09586 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumReads",
[email protected]f4134782013-08-29 21:25:20587 swap_info_.num_reads,
[email protected]aa1255b2013-07-31 22:03:09588 1, 100000000, 100);
589 UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumWrites",
[email protected]f4134782013-08-29 21:25:20590 swap_info_.num_writes,
[email protected]aa1255b2013-07-31 22:03:09591 1, 100000000, 100);
[email protected]48e303442013-07-18 19:13:15592
[email protected]f4134782013-08-29 21:25:20593 if (swap_info_.orig_data_size > 0 && swap_info_.compr_data_size > 0) {
[email protected]48e303442013-07-18 19:13:15594 UMA_HISTOGRAM_CUSTOM_COUNTS(
595 "Memory.Swap.CompressionRatio",
[email protected]f4134782013-08-29 21:25:20596 swap_info_.orig_data_size / swap_info_.compr_data_size,
[email protected]48e303442013-07-18 19:13:15597 1, 20, 20);
598 }
[email protected]23deabb72013-07-16 21:55:20599}
600
601#endif