BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / performance_monitor / performance_monitor.cc
blobdda007db70e5ddd59ed123d65e4319f8588b7da0
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 base::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 DCHECK_CURRENTLY_ON(BrowserThread::UI);
123 const base::ProcessHandle& handle = process_data.handle;
124 if (handle == base::kNullProcessHandle) {
125 // Process may not be valid yet.
126 return;
129 MetricsMap::iterator process_metrics_iter = metrics_map_.find(handle);
130 if (process_metrics_iter == metrics_map_.end()) {
131 // If we're not already watching the process, let's initialize it.
132 metrics_map_[handle].Initialize(process_data, current_update_sequence);
133 } else {
134 // If we are watching the process, touch it to keep it alive.
135 ProcessMetricsHistory& process_metrics = process_metrics_iter->second;
136 process_metrics.set_last_update_sequence(current_update_sequence);
140 void PerformanceMonitor::GatherMetricsMapOnIOThread(
141 int current_update_sequence) {
142 DCHECK_CURRENTLY_ON(BrowserThread::IO);
144 scoped_ptr<std::vector<ProcessMetricsMetadata>> process_data_list(
145 new std::vector<ProcessMetricsMetadata>());
147 // Find all child processes (does not include renderers), which has to be
148 // done on the IO thread.
149 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
150 ProcessMetricsMetadata child_process_data;
151 child_process_data.handle = iter.GetData().handle;
152 child_process_data.process_type = iter.GetData().process_type;
154 if (iter.GetData().name == base::ASCIIToUTF16(content::kFlashPluginName)) {
155 child_process_data.process_subtype = kProcessSubtypePPAPIFlash;
158 process_data_list->push_back(child_process_data);
161 // Add the current (browser) process.
162 ProcessMetricsMetadata browser_process_data;
163 browser_process_data.process_type = content::PROCESS_TYPE_BROWSER;
164 browser_process_data.handle = base::GetCurrentProcessHandle();
165 process_data_list->push_back(browser_process_data);
167 BrowserThread::PostTask(
168 BrowserThread::UI, FROM_HERE,
169 base::Bind(&PerformanceMonitor::MarkProcessesAsAliveOnUIThread,
170 base::Unretained(this), base::Passed(process_data_list.Pass()),
171 current_update_sequence));
174 void PerformanceMonitor::MarkProcessesAsAliveOnUIThread(
175 scoped_ptr<std::vector<ProcessMetricsMetadata>> process_data_list,
176 int current_update_sequence) {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI);
178 for (size_t i = 0; i < process_data_list->size(); ++i) {
179 MarkProcessAsAlive((*process_data_list)[i], current_update_sequence);
182 BrowserThread::PostTask(
183 BrowserThread::IO, FROM_HERE,
184 base::Bind(&PerformanceMonitor::UpdateMetricsOnIOThread,
185 base::Unretained(this), current_update_sequence));
188 void PerformanceMonitor::UpdateMetricsOnIOThread(int current_update_sequence) {
189 DCHECK_CURRENTLY_ON(BrowserThread::IO);
190 // Update metrics for all watched processes; remove dead entries from the map.
191 MetricsMap::iterator iter = metrics_map_.begin();
192 while (iter != metrics_map_.end()) {
193 ProcessMetricsHistory& process_metrics = iter->second;
194 if (process_metrics.last_update_sequence() != current_update_sequence) {
195 // Not touched this iteration; let's get rid of it.
196 metrics_map_.erase(iter++);
197 } else {
198 process_metrics.SampleMetrics();
199 ++iter;
203 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
204 base::Bind(&PerformanceMonitor::RunTriggersUIThread,
205 base::Unretained(this)));
208 void PerformanceMonitor::RunTriggersUIThread() {
209 DCHECK_CURRENTLY_ON(BrowserThread::UI);
210 for (auto it = metrics_map_.begin(); it != metrics_map_.end(); ++it) {
211 it->second.RunPerformanceTriggers();
214 StartGatherCycle();
217 } // namespace performance_monitor