Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: chrome/browser/memory_details.cc

Issue 16599016: Add UMA stats for predicted process counts with out-of-process iframes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add BrowsingInstance count, fix clang Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/memory_details.h" 5 #include "chrome/browser/memory_details.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_version_info.h" 8 #include "base/file_version_info.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/process_util.h" 10 #include "base/process_util.h"
(...skipping 21 matching lines...) Expand all
32 #include "ui/base/l10n/l10n_util.h" 32 #include "ui/base/l10n/l10n_util.h"
33 33
34 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 34 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
35 #include "content/public/browser/zygote_host_linux.h" 35 #include "content/public/browser/zygote_host_linux.h"
36 #endif 36 #endif
37 37
38 using base::StringPrintf; 38 using base::StringPrintf;
39 using content::BrowserChildProcessHostIterator; 39 using content::BrowserChildProcessHostIterator;
40 using content::BrowserThread; 40 using content::BrowserThread;
41 using content::NavigationEntry; 41 using content::NavigationEntry;
42 using content::RenderProcessHost;
42 using content::RenderViewHost; 43 using content::RenderViewHost;
43 using content::RenderWidgetHost; 44 using content::RenderWidgetHost;
45 using content::SiteInstance;
44 using content::WebContents; 46 using content::WebContents;
45 using extensions::Extension; 47 using extensions::Extension;
46 48
47 // static 49 // static
48 std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish( 50 std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish(
49 RendererProcessType type) { 51 RendererProcessType type) {
50 switch (type) { 52 switch (type) {
51 case RENDERER_NORMAL: 53 case RENDERER_NORMAL:
52 return "Tab"; 54 return "Tab";
53 case RENDERER_CHROME: 55 case RENDERER_CHROME:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 renderer_type(RENDERER_UNKNOWN) { 88 renderer_type(RENDERER_UNKNOWN) {
87 } 89 }
88 90
89 ProcessMemoryInformation::~ProcessMemoryInformation() {} 91 ProcessMemoryInformation::~ProcessMemoryInformation() {}
90 92
91 bool ProcessMemoryInformation::operator<( 93 bool ProcessMemoryInformation::operator<(
92 const ProcessMemoryInformation& rhs) const { 94 const ProcessMemoryInformation& rhs) const {
93 return working_set.priv < rhs.working_set.priv; 95 return working_set.priv < rhs.working_set.priv;
94 } 96 }
95 97
98 SiteData::SiteData() {}
99
100 SiteData::~SiteData() {}
101
96 ProcessData::ProcessData() {} 102 ProcessData::ProcessData() {}
97 103
98 ProcessData::ProcessData(const ProcessData& rhs) 104 ProcessData::ProcessData(const ProcessData& rhs)
99 : name(rhs.name), 105 : name(rhs.name),
100 process_name(rhs.process_name), 106 process_name(rhs.process_name),
101 processes(rhs.processes) { 107 processes(rhs.processes) {
102 } 108 }
103 109
104 ProcessData::~ProcessData() {} 110 ProcessData::~ProcessData() {}
105 111
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 for (; !iter.IsAtEnd(); iter.Advance()) { 249 for (; !iter.IsAtEnd(); iter.Advance()) {
244 const RenderWidgetHost* widget = iter.GetCurrentValue(); 250 const RenderWidgetHost* widget = iter.GetCurrentValue();
245 DCHECK(widget); 251 DCHECK(widget);
246 if (!widget || !widget->IsRenderView()) 252 if (!widget || !widget->IsRenderView())
247 continue; 253 continue;
248 254
249 RenderViewHost* host = 255 RenderViewHost* host =
250 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); 256 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
251 WebContents* contents = WebContents::FromRenderViewHost(host); 257 WebContents* contents = WebContents::FromRenderViewHost(host);
252 GURL url; 258 GURL url;
253 if (contents) 259 if (contents) {
254 url = contents->GetURL(); 260 url = contents->GetURL();
261 CollectSiteInfo(contents);
262 }
255 extensions::ViewType type = extensions::GetViewType(contents); 263 extensions::ViewType type = extensions::GetViewType(contents);
256 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) { 264 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
257 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME; 265 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
258 } else if (extension_process_map && 266 } else if (extension_process_map &&
259 extension_process_map->Contains(host->GetProcess()->GetID())) { 267 extension_process_map->Contains(host->GetProcess()->GetID())) {
260 // For our purposes, don't count processes containing only hosted apps 268 // For our purposes, don't count processes containing only hosted apps
261 // as extension processes. See also: crbug.com/102533. 269 // as extension processes. See also: crbug.com/102533.
262 std::set<std::string> extension_ids = 270 std::set<std::string> extension_ids =
263 extension_process_map->GetExtensionsInProcess( 271 extension_process_map->GetExtensionsInProcess(
264 host->GetProcess()->GetID()); 272 host->GetProcess()->GetID());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 index--; 368 index--;
361 } 369 }
362 } 370 }
363 371
364 if (user_metrics_mode_ == UPDATE_USER_METRICS) 372 if (user_metrics_mode_ == UPDATE_USER_METRICS)
365 UpdateHistograms(); 373 UpdateHistograms();
366 374
367 OnDetailsAvailable(); 375 OnDetailsAvailable();
368 } 376 }
369 377
378 void MemoryDetails::CollectSiteInfo(WebContents* contents) {
379 ProcessData* const chrome_browser = ChromeBrowser();
380
381 // Keep track of data for each BrowserContext separately, since tabs in
382 // different BrowserContexts can't share processes.
383 content::BrowserContext* browser_context = contents->GetBrowserContext();
384 SiteData* site_data = &chrome_browser->site_data[browser_context];
385
386 // Find the BrowsingInstance this WebContents belongs to by iterating over
387 // the "primary" SiteInstances of each BrowsingInstance we've seen so far.
388 SiteInstance* instance = contents->GetSiteInstance();
389 SiteInstance* primary = NULL;
390 for (size_t i = 0; i < site_data->instances.size(); ++i) {
391 if (instance->IsRelatedSiteInstance(site_data->instances[i])) {
392 primary = site_data->instances[i];
393 break;
394 }
395 }
396 if (!primary) {
397 // Remember this as the "primary" SiteInstance of a new BrowsingInstance.
398 primary = instance;
399 site_data->instances.push_back(instance);
400 }
401
402 // Now keep track of how many sites we have in this BrowsingInstance (and
403 // overall), including sites in iframes.
404 std::set<GURL> sites_in_tab = contents->GetSitesInTab();
405 for (std::set<GURL>::iterator iter = sites_in_tab.begin();
406 iter != sites_in_tab.end(); ++iter) {
nasko 2013/06/11 20:16:37 nit: Shouldn't the increment part of the loop be o
Charlie Reis 2013/06/11 21:36:39 No, this looks like a common pattern. You only ne
407 // Skip about:blank, since we won't usually give it its own process.
408 if (iter->is_empty())
nasko 2013/06/11 20:16:37 Is "about:blank" an actual empty GURL? I thought w
Charlie Reis 2013/06/11 21:36:39 It comes from GetSiteForURL, which has the comment
409 continue;
410
411 // Make sure we don't overcount process-per-site sites, like the NTP.
412 if (RenderProcessHost::ShouldUseProcessPerSite(browser_context, *iter) &&
413 site_data->sites.find(*iter) != site_data->sites.end()) {
414 continue;
415 }
416
417 site_data->sites.insert(*iter);
418 site_data->instance_site_map[primary->GetId()].insert(*iter);
419
420 // Also keep track of how things would look if we only isolated HTTPS sites.
421 // In this model, all HTTP sites are grouped into one "http://" site. HTTPS
422 // and other schemes (e.g., chrome:) are still isolated.
423 GURL https_site = iter->SchemeIs("http") ? GURL("http://") : *iter;
424 site_data->https_sites.insert(https_site);
425 site_data->instance_https_site_map[primary->GetId()].insert(https_site);
426 }
427 }
428
370 void MemoryDetails::UpdateHistograms() { 429 void MemoryDetails::UpdateHistograms() {
371 // Reports a set of memory metrics to UMA. 430 // Reports a set of memory metrics to UMA.
372 // Memory is measured in KB. 431 // Memory is measured in KB.
373 432
374 const ProcessData& browser = *ChromeBrowser(); 433 const ProcessData& browser = *ChromeBrowser();
375 size_t aggregate_memory = 0; 434 size_t aggregate_memory = 0;
376 int chrome_count = 0; 435 int chrome_count = 0;
377 int extension_count = 0; 436 int extension_count = 0;
378 int plugin_count = 0; 437 int plugin_count = 0;
379 int pepper_plugin_count = 0; 438 int pepper_plugin_count = 0;
380 int pepper_plugin_broker_count = 0; 439 int pepper_plugin_broker_count = 0;
381 int renderer_count = 0; 440 int renderer_count = 0;
382 int other_count = 0; 441 int other_count = 0;
383 int worker_count = 0; 442 int worker_count = 0;
443 int process_limit = RenderProcessHost::GetMaxRendererProcessCount();
384 for (size_t index = 0; index < browser.processes.size(); index++) { 444 for (size_t index = 0; index < browser.processes.size(); index++) {
385 int sample = static_cast<int>(browser.processes[index].working_set.priv); 445 int sample = static_cast<int>(browser.processes[index].working_set.priv);
386 aggregate_memory += sample; 446 aggregate_memory += sample;
387 switch (browser.processes[index].process_type) { 447 switch (browser.processes[index].process_type) {
388 case content::PROCESS_TYPE_BROWSER: 448 case content::PROCESS_TYPE_BROWSER:
389 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample); 449 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
390 break; 450 break;
391 case content::PROCESS_TYPE_RENDERER: { 451 case content::PROCESS_TYPE_RENDERER: {
392 ProcessMemoryInformation::RendererProcessType renderer_type = 452 ProcessMemoryInformation::RendererProcessType renderer_type =
393 browser.processes[index].renderer_type; 453 browser.processes[index].renderer_type;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore", 520 UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore",
461 RenderWidgetHost::BackingStoreMemorySize() / 1024); 521 RenderWidgetHost::BackingStoreMemorySize() / 1024);
462 #if defined(OS_CHROMEOS) 522 #if defined(OS_CHROMEOS)
463 // Chrome OS exposes system-wide graphics driver memory which has historically 523 // Chrome OS exposes system-wide graphics driver memory which has historically
464 // been a source of leak/bloat. 524 // been a source of leak/bloat.
465 base::SystemMemoryInfoKB meminfo; 525 base::SystemMemoryInfoKB meminfo;
466 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1) 526 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1)
467 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024); 527 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
468 #endif 528 #endif
469 529
530 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
470 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount", 531 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
471 static_cast<int>(browser.processes.size())); 532 static_cast<int>(browser.processes.size()));
472 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count); 533 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
473 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count); 534 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
474 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count); 535 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
475 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count); 536 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
476 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount", 537 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
477 pepper_plugin_count); 538 pepper_plugin_count);
478 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount", 539 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
479 pepper_plugin_broker_count); 540 pepper_plugin_broker_count);
480 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); 541 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
481 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); 542 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
482 // TODO(viettrungluu): Do we want separate counts for the other 543 // TODO(viettrungluu): Do we want separate counts for the other
483 // (platform-specific) process types? 544 // (platform-specific) process types?
484 545
485 int total_sample = static_cast<int>(aggregate_memory / 1000); 546 int total_sample = static_cast<int>(aggregate_memory / 1000);
486 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); 547 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
548
549 // Sum the number of sites and SiteInstances in each BrowserContext.
550 int num_sites = 0;
551 int num_https_sites = 0;
552 int num_browsing_instances = 0;
553 int num_isolated_site_instances = 0;
554 int num_isolated_https_site_instances = 0;
555 for (BrowserContextSiteDataMap::const_iterator i = browser.site_data.begin();
556 i != browser.site_data.end(); ++i) {
557 num_sites += i->second.sites.size();
558 num_https_sites += i->second.https_sites.size();
559 num_browsing_instances += i->second.instance_site_map.size();
560 for (BrowsingInstanceSiteMap::const_iterator iter =
561 i->second.instance_site_map.begin();
562 iter != i->second.instance_site_map.end(); ++iter) {
563 num_isolated_site_instances += iter->second.size();
564 }
565 for (BrowsingInstanceSiteMap::const_iterator iter =
566 i->second.instance_https_site_map.begin();
567 iter != i->second.instance_https_site_map.end(); ++iter) {
568 num_isolated_https_site_instances += iter->second.size();
569 }
570 }
571
572 // Predict the number of processes needed when isolating all sites and when
573 // isolating only HTTPS sites.
574 int process_count_lower_bound = num_sites;
575 int process_count_upper_bound = num_sites + process_limit - 1;
576 int process_count_estimate = std::min(
577 num_isolated_site_instances, process_count_upper_bound);
578
579 int process_count_https_lower_bound = num_https_sites;
580 int process_count_https_upper_bound = num_https_sites + process_limit - 1;
581 int process_count_https_estimate = std::min(
582 num_isolated_https_site_instances, process_count_https_upper_bound);
583
584 // Just renderer process count:
585 int all_renderer_count = renderer_count + chrome_count + extension_count;
586 UMA_HISTOGRAM_COUNTS_100("SiteIsolation.CurrentRendererProcessCount",
587 all_renderer_count);
588 UMA_HISTOGRAM_COUNTS_100(
589 "SiteIsolation.BrowsingInstanceCount",
590 num_browsing_instances);
591 UMA_HISTOGRAM_COUNTS_100(
592 "SiteIsolation.IsolateAllSitesProcessCountNoLimit",
593 num_isolated_site_instances);
594 UMA_HISTOGRAM_COUNTS_100(
595 "SiteIsolation.IsolateAllSitesProcessCountLowerBound",
596 process_count_lower_bound);
597 UMA_HISTOGRAM_COUNTS_100(
598 "SiteIsolation.IsolateAllSitesProcessCountEstimate",
599 process_count_estimate);
600 UMA_HISTOGRAM_COUNTS_100(
601 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit",
602 num_isolated_https_site_instances);
603 UMA_HISTOGRAM_COUNTS_100(
604 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound",
605 process_count_https_lower_bound);
606 UMA_HISTOGRAM_COUNTS_100(
607 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate",
608 process_count_https_estimate);
609
610 // Total process count:
611 int non_renderer_count = browser.processes.size() - all_renderer_count;
612 UMA_HISTOGRAM_COUNTS_100(
613 "SiteIsolation.IsolateAllSitesTotalProcessCountEstimate",
614 process_count_estimate + non_renderer_count);
615 UMA_HISTOGRAM_COUNTS_100(
616 "SiteIsolation.IsolateHttpsSitesTotalProcessCountEstimate",
617 process_count_https_estimate + non_renderer_count);
487 } 618 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698