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) { | |
darin (slow to review)
2013/06/12 04:40:48
nit: It is perhaps expanding the scope of this cla
Charlie Reis
2013/06/12 18:59:16
It's kind of intermediate data to report process c
| |
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) { | |
407 // Skip about:blank, since we won't usually give it its own process. | |
408 // Because about:blank has no host, its site URL will be blank. | |
409 if (iter->is_empty()) | |
410 continue; | |
411 | |
412 // Make sure we don't overcount process-per-site sites, like the NTP. | |
413 if (RenderProcessHost::ShouldUseProcessPerSite(browser_context, *iter) && | |
414 site_data->sites.find(*iter) != site_data->sites.end()) { | |
415 continue; | |
416 } | |
417 | |
418 site_data->sites.insert(*iter); | |
419 site_data->instance_site_map[primary->GetId()].insert(*iter); | |
420 | |
421 // Also keep track of how things would look if we only isolated HTTPS sites. | |
422 // In this model, all HTTP sites are grouped into one "http://" site. HTTPS | |
423 // and other schemes (e.g., chrome:) are still isolated. | |
424 GURL https_site = iter->SchemeIs("http") ? GURL("http://") : *iter; | |
425 site_data->https_sites.insert(https_site); | |
426 site_data->instance_https_site_map[primary->GetId()].insert(https_site); | |
427 } | |
428 } | |
429 | |
370 void MemoryDetails::UpdateHistograms() { | 430 void MemoryDetails::UpdateHistograms() { |
371 // Reports a set of memory metrics to UMA. | 431 // Reports a set of memory metrics to UMA. |
372 // Memory is measured in KB. | 432 // Memory is measured in KB. |
373 | 433 |
374 const ProcessData& browser = *ChromeBrowser(); | 434 const ProcessData& browser = *ChromeBrowser(); |
375 size_t aggregate_memory = 0; | 435 size_t aggregate_memory = 0; |
376 int chrome_count = 0; | 436 int chrome_count = 0; |
377 int extension_count = 0; | 437 int extension_count = 0; |
378 int plugin_count = 0; | 438 int plugin_count = 0; |
379 int pepper_plugin_count = 0; | 439 int pepper_plugin_count = 0; |
380 int pepper_plugin_broker_count = 0; | 440 int pepper_plugin_broker_count = 0; |
381 int renderer_count = 0; | 441 int renderer_count = 0; |
382 int other_count = 0; | 442 int other_count = 0; |
383 int worker_count = 0; | 443 int worker_count = 0; |
444 int process_limit = RenderProcessHost::GetMaxRendererProcessCount(); | |
384 for (size_t index = 0; index < browser.processes.size(); index++) { | 445 for (size_t index = 0; index < browser.processes.size(); index++) { |
385 int sample = static_cast<int>(browser.processes[index].working_set.priv); | 446 int sample = static_cast<int>(browser.processes[index].working_set.priv); |
386 aggregate_memory += sample; | 447 aggregate_memory += sample; |
387 switch (browser.processes[index].process_type) { | 448 switch (browser.processes[index].process_type) { |
388 case content::PROCESS_TYPE_BROWSER: | 449 case content::PROCESS_TYPE_BROWSER: |
389 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample); | 450 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample); |
390 break; | 451 break; |
391 case content::PROCESS_TYPE_RENDERER: { | 452 case content::PROCESS_TYPE_RENDERER: { |
392 ProcessMemoryInformation::RendererProcessType renderer_type = | 453 ProcessMemoryInformation::RendererProcessType renderer_type = |
393 browser.processes[index].renderer_type; | 454 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", | 521 UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore", |
461 RenderWidgetHost::BackingStoreMemorySize() / 1024); | 522 RenderWidgetHost::BackingStoreMemorySize() / 1024); |
462 #if defined(OS_CHROMEOS) | 523 #if defined(OS_CHROMEOS) |
463 // Chrome OS exposes system-wide graphics driver memory which has historically | 524 // Chrome OS exposes system-wide graphics driver memory which has historically |
464 // been a source of leak/bloat. | 525 // been a source of leak/bloat. |
465 base::SystemMemoryInfoKB meminfo; | 526 base::SystemMemoryInfoKB meminfo; |
466 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1) | 527 if (base::GetSystemMemoryInfo(&meminfo) && meminfo.gem_size != -1) |
467 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024); | 528 UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024); |
468 #endif | 529 #endif |
469 | 530 |
531 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit); | |
470 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount", | 532 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount", |
471 static_cast<int>(browser.processes.size())); | 533 static_cast<int>(browser.processes.size())); |
472 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count); | 534 UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count); |
473 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count); | 535 UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count); |
474 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count); | 536 UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count); |
475 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count); | 537 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count); |
476 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount", | 538 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount", |
477 pepper_plugin_count); | 539 pepper_plugin_count); |
478 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount", | 540 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount", |
479 pepper_plugin_broker_count); | 541 pepper_plugin_broker_count); |
480 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); | 542 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); |
481 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); | 543 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); |
482 // TODO(viettrungluu): Do we want separate counts for the other | 544 // TODO(viettrungluu): Do we want separate counts for the other |
483 // (platform-specific) process types? | 545 // (platform-specific) process types? |
484 | 546 |
485 int total_sample = static_cast<int>(aggregate_memory / 1000); | 547 int total_sample = static_cast<int>(aggregate_memory / 1000); |
486 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); | 548 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); |
549 | |
550 // Sum the number of sites and SiteInstances in each BrowserContext. | |
551 int num_sites = 0; | |
552 int num_https_sites = 0; | |
553 int num_browsing_instances = 0; | |
554 int num_isolated_site_instances = 0; | |
555 int num_isolated_https_site_instances = 0; | |
556 for (BrowserContextSiteDataMap::const_iterator i = browser.site_data.begin(); | |
557 i != browser.site_data.end(); ++i) { | |
558 num_sites += i->second.sites.size(); | |
559 num_https_sites += i->second.https_sites.size(); | |
560 num_browsing_instances += i->second.instance_site_map.size(); | |
561 for (BrowsingInstanceSiteMap::const_iterator iter = | |
562 i->second.instance_site_map.begin(); | |
563 iter != i->second.instance_site_map.end(); ++iter) { | |
564 num_isolated_site_instances += iter->second.size(); | |
565 } | |
566 for (BrowsingInstanceSiteMap::const_iterator iter = | |
567 i->second.instance_https_site_map.begin(); | |
568 iter != i->second.instance_https_site_map.end(); ++iter) { | |
569 num_isolated_https_site_instances += iter->second.size(); | |
570 } | |
571 } | |
572 | |
573 // Predict the number of processes needed when isolating all sites and when | |
574 // isolating only HTTPS sites. | |
575 int process_count_lower_bound = num_sites; | |
576 int process_count_upper_bound = num_sites + process_limit - 1; | |
577 int process_count_estimate = std::min( | |
578 num_isolated_site_instances, process_count_upper_bound); | |
579 | |
580 int process_count_https_lower_bound = num_https_sites; | |
581 int process_count_https_upper_bound = num_https_sites + process_limit - 1; | |
582 int process_count_https_estimate = std::min( | |
583 num_isolated_https_site_instances, process_count_https_upper_bound); | |
584 | |
585 // Just renderer process count: | |
586 int all_renderer_count = renderer_count + chrome_count + extension_count; | |
587 UMA_HISTOGRAM_COUNTS_100("SiteIsolation.CurrentRendererProcessCount", | |
588 all_renderer_count); | |
589 UMA_HISTOGRAM_COUNTS_100( | |
590 "SiteIsolation.BrowsingInstanceCount", | |
591 num_browsing_instances); | |
592 UMA_HISTOGRAM_COUNTS_100( | |
593 "SiteIsolation.IsolateAllSitesProcessCountNoLimit", | |
594 num_isolated_site_instances); | |
595 UMA_HISTOGRAM_COUNTS_100( | |
596 "SiteIsolation.IsolateAllSitesProcessCountLowerBound", | |
597 process_count_lower_bound); | |
598 UMA_HISTOGRAM_COUNTS_100( | |
599 "SiteIsolation.IsolateAllSitesProcessCountEstimate", | |
600 process_count_estimate); | |
601 UMA_HISTOGRAM_COUNTS_100( | |
602 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit", | |
603 num_isolated_https_site_instances); | |
604 UMA_HISTOGRAM_COUNTS_100( | |
605 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound", | |
606 process_count_https_lower_bound); | |
607 UMA_HISTOGRAM_COUNTS_100( | |
608 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate", | |
609 process_count_https_estimate); | |
610 | |
611 // Total process count: | |
612 int non_renderer_count = browser.processes.size() - all_renderer_count; | |
613 UMA_HISTOGRAM_COUNTS_100( | |
614 "SiteIsolation.IsolateAllSitesTotalProcessCountEstimate", | |
615 process_count_estimate + non_renderer_count); | |
616 UMA_HISTOGRAM_COUNTS_100( | |
617 "SiteIsolation.IsolateHttpsSitesTotalProcessCountEstimate", | |
618 process_count_https_estimate + non_renderer_count); | |
487 } | 619 } |
OLD | NEW |