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/time/time.h"
10 #include "content/public/browser/browser_child_process_host.h"
11 #include "content/public/browser/browser_child_process_host_iterator.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/child_process_data.h"
14 #include "content/public/browser/render_process_host.h"
16 using content::BrowserThread
;
20 // The default interval at which PerformanceMonitor performs its timed
22 const int kGatherIntervalInSeconds
= 120;
25 namespace performance_monitor
{
27 PerformanceMonitor::PerformanceMonitor() {
30 PerformanceMonitor::~PerformanceMonitor() {
34 PerformanceMonitor
* PerformanceMonitor::GetInstance() {
35 return Singleton
<PerformanceMonitor
>::get();
38 void PerformanceMonitor::StartGatherCycle() {
39 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
40 repeating_timer_
.Start(FROM_HERE
,
41 base::TimeDelta::FromSeconds(kGatherIntervalInSeconds
),
43 &PerformanceMonitor::GatherMetricsMapOnUIThread
);
46 void PerformanceMonitor::GatherMetricsMapOnUIThread() {
47 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
49 static int current_update_sequence
= 0;
50 // Even in the "somewhat" unlikely event this wraps around,
51 // it doesn't matter. We just check it for inequality.
52 current_update_sequence
++;
54 // Find all render child processes; has to be done on the UI thread.
55 for (content::RenderProcessHost::iterator rph_iter
=
56 content::RenderProcessHost::AllHostsIterator();
57 !rph_iter
.IsAtEnd(); rph_iter
.Advance()) {
58 base::ProcessHandle handle
= rph_iter
.GetCurrentValue()->GetHandle();
59 MarkProcessAsAlive(handle
, content::PROCESS_TYPE_RENDERER
,
60 current_update_sequence
);
63 BrowserThread::PostTask(
66 base::Bind(&PerformanceMonitor::GatherMetricsMapOnIOThread
,
67 base::Unretained(this),
68 current_update_sequence
));
71 void PerformanceMonitor::MarkProcessAsAlive(const base::ProcessHandle
& handle
,
73 int current_update_sequence
) {
75 // Process may not be valid yet.
79 MetricsMap::iterator process_metrics_iter
= metrics_map_
.find(handle
);
80 if (process_metrics_iter
== metrics_map_
.end()) {
81 // If we're not already watching the process, let's initialize it.
83 .Initialize(handle
, process_type
, current_update_sequence
);
85 // If we are watching the process, touch it to keep it alive.
86 ProcessMetricsHistory
& process_metrics
= process_metrics_iter
->second
;
87 process_metrics
.set_last_update_sequence(current_update_sequence
);
91 void PerformanceMonitor::GatherMetricsMapOnIOThread(
92 int current_update_sequence
) {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
95 // Find all child processes (does not include renderers), which has to be
96 // done on the IO thread.
97 for (content::BrowserChildProcessHostIterator iter
; !iter
.Done(); ++iter
) {
98 const content::ChildProcessData
& child_process_data
= iter
.GetData();
99 base::ProcessHandle handle
= child_process_data
.handle
;
100 MarkProcessAsAlive(handle
, child_process_data
.process_type
,
101 current_update_sequence
);
104 // Add the current (browser) process.
105 MarkProcessAsAlive(base::GetCurrentProcessHandle(),
106 content::PROCESS_TYPE_BROWSER
, current_update_sequence
);
108 double cpu_usage
= 0.0;
109 size_t private_memory_sum
= 0;
110 size_t shared_memory_sum
= 0;
112 // Update metrics for all watched processes; remove dead entries from the map.
113 MetricsMap::iterator iter
= metrics_map_
.begin();
114 while (iter
!= metrics_map_
.end()) {
115 ProcessMetricsHistory
& process_metrics
= iter
->second
;
116 if (process_metrics
.last_update_sequence() != current_update_sequence
) {
117 // Not touched this iteration; let's get rid of it.
118 metrics_map_
.erase(iter
++);
120 process_metrics
.SampleMetrics();
122 // Gather averages of previously sampled metrics.
123 cpu_usage
+= process_metrics
.GetAverageCPUUsage();
125 size_t private_memory
= 0;
126 size_t shared_memory
= 0;
127 process_metrics
.GetAverageMemoryBytes(&private_memory
, &shared_memory
);
128 private_memory_sum
+= private_memory
;
129 shared_memory_sum
+= shared_memory
;
131 process_metrics
.EndOfCycle();
138 } // namespace performance_monitor