Fire an error if a pref used in the UI is missing once all prefs are fetched.
[chromium-blink-merge.git] / chrome / browser / performance_monitor / performance_monitor.cc
blob5cf2ce4aee8d6136d9941b7c97f4d3ce87aa0f53
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
3 // found in the LICENSE file.
5 #include "chrome/browser/performance_monitor/performance_monitor.h"
7 #include "base/memory/singleton.h"
8 #include "base/process/process_iterator.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h"
11 #include "content/public/browser/browser_child_process_host.h"
12 #include "content/public/browser/browser_child_process_host_iterator.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/child_process_data.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/common/content_constants.h"
18 #if defined(ENABLE_EXTENSIONS)
19 #include "extensions/browser/extension_host.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/manifest_handlers/background_info.h"
22 #endif
24 using content::BrowserThread;
26 namespace {
28 // The default interval at which PerformanceMonitor performs its timed
29 // collections.
30 const int kGatherIntervalInSeconds = 120;
32 } // namespace
34 namespace performance_monitor {
36 PerformanceMonitor::PerformanceMonitor() {
39 PerformanceMonitor::~PerformanceMonitor() {
42 // static
43 PerformanceMonitor* PerformanceMonitor::GetInstance() {
44 return Singleton<PerformanceMonitor>::get();
47 void PerformanceMonitor::StartGatherCycle() {
48 DCHECK_CURRENTLY_ON(BrowserThread::UI);
49 repeating_timer_.Start(FROM_HERE,
50 base::TimeDelta::FromSeconds(kGatherIntervalInSeconds),
51 this, &PerformanceMonitor::GatherMetricsMapOnUIThread);
54 namespace {
56 void GatherMetricsForRenderProcess(content::RenderProcessHost* host,
57 ProcessMetricsMetadata& data) {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI);
59 #if defined(ENABLE_EXTENSIONS)
60 content::BrowserContext* browser_context = host->GetBrowserContext();
61 extensions::ProcessMap* extension_process_map =
62 extensions::ProcessMap::Get(browser_context);
64 std::set<std::string> extension_ids =
65 extension_process_map->GetExtensionsInProcess(host->GetID());
67 // We only collect more granular metrics when there's only one extension
68 // running in a given renderer, to reduce noise.
69 if (extension_ids.size() != 1)
70 return;
72 extensions::ExtensionRegistry* extension_registry =
73 extensions::ExtensionRegistry::Get(browser_context);
75 const extensions::Extension* extension =
76 extension_registry->enabled_extensions().GetByID(*extension_ids.begin());
78 if (!extension)
79 return;
81 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(extension)) {
82 data.process_subtype = kProcessSubtypeExtensionPersistent;
83 } else {
84 data.process_subtype = kProcessSubtypeExtensionEvent;
86 #endif
89 } // namespace
91 void PerformanceMonitor::GatherMetricsMapOnUIThread() {
92 DCHECK_CURRENTLY_ON(BrowserThread::UI);
94 static int current_update_sequence = 0;
95 // Even in the "somewhat" unlikely event this wraps around,
96 // it doesn't matter. We just check it for inequality.
97 current_update_sequence++;
99 // Find all render child processes; has to be done on the UI thread.
100 for (content::RenderProcessHost::iterator rph_iter =
101 content::RenderProcessHost::AllHostsIterator();
102 !rph_iter.IsAtEnd(); rph_iter.Advance()) {
103 content::RenderProcessHost* host = rph_iter.GetCurrentValue();
104 ProcessMetricsMetadata data;
105 data.process_type = content::PROCESS_TYPE_RENDERER;
106 data.handle = host->GetHandle();
108 GatherMetricsForRenderProcess(host, data);
109 MarkProcessAsAlive(data, current_update_sequence);
112 BrowserThread::PostTask(
113 BrowserThread::IO, FROM_HERE,
114 base::Bind(&PerformanceMonitor::GatherMetricsMapOnIOThread,
115 base::Unretained(this), current_update_sequence));
118 void PerformanceMonitor::MarkProcessAsAlive(
119 const ProcessMetricsMetadata& process_data,
120 int current_update_sequence) {
121 const base::ProcessHandle& handle = process_data.handle;
122 if (handle == base::kNullProcessHandle) {
123 // Process may not be valid yet.
124 return;
127 MetricsMap::iterator process_metrics_iter = metrics_map_.find(handle);
128 if (process_metrics_iter == metrics_map_.end()) {
129 // If we're not already watching the process, let's initialize it.
130 metrics_map_[handle].Initialize(process_data, current_update_sequence);
131 } else {
132 // If we are watching the process, touch it to keep it alive.
133 ProcessMetricsHistory& process_metrics = process_metrics_iter->second;
134 process_metrics.set_last_update_sequence(current_update_sequence);
138 void PerformanceMonitor::GatherMetricsMapOnIOThread(
139 int current_update_sequence) {
140 DCHECK_CURRENTLY_ON(BrowserThread::IO);
142 // Find all child processes (does not include renderers), which has to be
143 // done on the IO thread.
144 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
145 ProcessMetricsMetadata child_process_data;
146 child_process_data.handle = iter.GetData().handle;
147 child_process_data.process_type = iter.GetData().process_type;
149 if (iter.GetData().name == base::ASCIIToUTF16(content::kFlashPluginName)) {
150 child_process_data.process_subtype = kProcessSubtypePPAPIFlash;
153 MarkProcessAsAlive(child_process_data, current_update_sequence);
156 // Add the current (browser) process.
157 ProcessMetricsMetadata browser_process_data;
158 browser_process_data.process_type = content::PROCESS_TYPE_BROWSER;
159 browser_process_data.handle = base::GetCurrentProcessHandle();
160 MarkProcessAsAlive(browser_process_data, current_update_sequence);
162 // Update metrics for all watched processes; remove dead entries from the map.
163 MetricsMap::iterator iter = metrics_map_.begin();
164 while (iter != metrics_map_.end()) {
165 ProcessMetricsHistory& process_metrics = iter->second;
166 if (process_metrics.last_update_sequence() != current_update_sequence) {
167 // Not touched this iteration; let's get rid of it.
168 metrics_map_.erase(iter++);
169 } else {
170 process_metrics.SampleMetrics();
171 ++iter;
176 } // namespace performance_monitor