Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(778)

Side by Side Diff: chrome/browser/power/process_power_collector.cc

Issue 472383002: Add ProcessPowerCollector to audit power information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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.
4 #include "chrome/browser/power/process_power_collector.h"
5
6 #include "apps/app_window.h"
7 #include "apps/app_window_registry.h"
8 #include "base/process/process_handle.h"
9 #include "base/process/process_metrics.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
14 #include "components/power/origin_power_map.h"
15 #include "components/power/origin_power_map_factory.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "url/gurl.h"
20
21 #if defined(OS_CHROMEOS)
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
24 #endif
25
26 namespace {
27 const int kSecondsPerSample = 30;
28 }
29
30 ProcessPowerCollector::PerProcessData::PerProcessData(
31 scoped_ptr<base::ProcessMetrics> metrics,
32 const GURL& origin,
33 Profile* profile)
34 : metrics_(metrics.Pass()),
35 profile_(profile),
36 last_origin_(origin),
37 last_cpu_percent_(0),
38 seen_this_cycle_(true) {
39 }
40
41 ProcessPowerCollector::PerProcessData::PerProcessData()
42 : profile_(NULL), last_cpu_percent_(0.0), seen_this_cycle_(false) {
43 }
44
45 ProcessPowerCollector::PerProcessData::~PerProcessData() {
46 }
47
48 ProcessPowerCollector::ProcessPowerCollector()
49 : scale_factor_(1.0), has_started_(false) {
50 #if defined(OS_CHROMEOS)
51 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
52 this);
53 #endif
54 }
55
56 ProcessPowerCollector::~ProcessPowerCollector() {
57 #if defined(OS_CHROMEOS)
58 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
59 this);
60 #endif
61 }
62
63 #if defined(OS_CHROMEOS)
64 void ProcessPowerCollector::PowerChanged(
65 const power_manager::PowerSupplyProperties& prop) {
66 if (prop.battery_state() ==
67 power_manager::PowerSupplyProperties::DISCHARGING) {
68 if (has_started_ && !timer_.IsRunning())
69 StartTimer();
70 scale_factor_ = prop.battery_discharge_rate();
71 } else {
72 timer_.Stop();
73 }
74 }
75 #endif
76
77 void ProcessPowerCollector::StartTimer() {
78 DCHECK(!timer_.IsRunning());
79 has_started_ = true;
80 timer_.Start(FROM_HERE,
81 base::TimeDelta::FromSeconds(kSecondsPerSample),
82 this,
83 &ProcessPowerCollector::HandleUpdateTimeout);
84 }
85
86 double ProcessPowerCollector::UpdatePowerConsumptionForTesting() {
87 return UpdatePowerConsumption();
88 }
89
90 double ProcessPowerCollector::UpdatePowerConsumption() {
91 double total_cpu_percent = SynchronizeProcesses();
92
93 for (ProcessMetricsMap::iterator it = metrics_map_.begin();
94 it != metrics_map_.end();
95 ++it) {
96 // Invalidate the process for the next cycle.
97 it->second->set_seen_this_cycle(false);
98 }
99
100 RecordCpuUsageByOrigin(total_cpu_percent);
101 return total_cpu_percent;
102 }
103
104 void ProcessPowerCollector::HandleUpdateTimeout() {
105 UpdatePowerConsumption();
106 }
107
108 double ProcessPowerCollector::SynchronizeProcesses() {
109 // Update all tabs.
110 for (TabContentsIterator it; !it.done(); it.Next()) {
111 content::RenderProcessHost* render_process = it->GetRenderProcessHost();
112 // Skip incognito web contents.
113 if (render_process->GetBrowserContext()->IsOffTheRecord())
114 continue;
115 UpdateProcessInMap(render_process, it->GetLastCommittedURL().GetOrigin());
116 }
117
118 // Iterate over all profiles to find all app windows to attribute all apps.
119 ProfileManager* pm = g_browser_process->profile_manager();
120 std::vector<Profile*> open_profiles = pm->GetLoadedProfiles();
121 for (std::vector<Profile*>::const_iterator it = open_profiles.begin();
122 it != open_profiles.end();
123 ++it) {
124 const apps::AppWindowRegistry::AppWindowList& app_windows =
125 apps::AppWindowRegistry::Get(*it)->app_windows();
126 for (apps::AppWindowRegistry::AppWindowList::const_iterator itr =
127 app_windows.begin();
128 itr != app_windows.end();
129 ++itr) {
130 content::WebContents* web_contents = (*itr)->web_contents();
131
132 UpdateProcessInMap(web_contents->GetRenderProcessHost(),
133 web_contents->GetLastCommittedURL().GetOrigin());
134 }
135 }
136
137 // Remove invalid processes and sum up the cpu cycle.
138 double total_cpu_percent = 0.0;
139 ProcessMetricsMap::iterator it = metrics_map_.begin();
140 while (it != metrics_map_.end()) {
141 if (!it->second->seen_this_cycle()) {
142 metrics_map_.erase(it++);
143 continue;
144 }
145
146 total_cpu_percent += it->second->last_cpu_percent();
147 ++it;
148 }
149
150 return total_cpu_percent;
151 }
152
153 void ProcessPowerCollector::RecordCpuUsageByOrigin(double total_cpu_percent) {
154 DCHECK_GE(total_cpu_percent, 0);
155 if (total_cpu_percent == 0)
156 return;
157
158 for (ProcessMetricsMap::iterator it = metrics_map_.begin();
159 it != metrics_map_.end();
160 ++it) {
161 double last_process_power_usage = it->second->last_cpu_percent();
162 last_process_power_usage *= scale_factor_ / total_cpu_percent;
163
164 GURL origin = it->second->last_origin();
165 power::OriginPowerMap* origin_power_map =
166 power::OriginPowerMapFactory::GetForBrowserContext(
167 it->second->profile());
168 DCHECK(origin_power_map);
169 origin_power_map->AddPowerForOrigin(origin, last_process_power_usage);
170 }
171 }
172
173 void ProcessPowerCollector::UpdateProcessInMap(
174 const content::RenderProcessHost* rph,
175 const GURL& origin) {
176 base::ProcessHandle handle = rph->GetHandle();
177 if (metrics_map_.find(handle) == metrics_map_.end()) {
178 metrics_map_[handle] = linked_ptr<PerProcessData>(new PerProcessData(
179 #if defined(OS_MACOSX)
180 scoped_ptr<base::ProcessMetrics>(
181 base::ProcessMetrics::CreateProcessMetrics(handle, NULL)),
182 #else
183 scoped_ptr<base::ProcessMetrics>(
184 base::ProcessMetrics::CreateProcessMetrics(handle)),
185 #endif
186 origin,
187 Profile::FromBrowserContext(rph->GetBrowserContext())));
188 }
189
190 linked_ptr<PerProcessData>& process_data = metrics_map_[handle];
191 process_data->set_last_cpu_percent(std::max(
192 0.0,
193 cpu_usage_callback_.is_null() ? process_data->metrics()->GetCPUUsage()
194 : cpu_usage_callback_.Run(handle)));
195 process_data->set_seen_this_cycle(true);
196 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698