OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |