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

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: Generalize CrOS values. 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"
sky 2014/08/25 20:43:43 nit: newline between 3/4.
Daniel Nishi 2014/08/25 21:08:33 Done.
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),
43 last_cpu_percent_(0.0),
44 seen_this_cycle_(false) {
45 }
46
47 ProcessPowerCollector::PerProcessData::~PerProcessData() {
48 }
49
50 ProcessPowerCollector::ProcessPowerCollector()
51 : scale_factor_(1.0),
52 is_initialized_(false)
53 {
54 #if defined(OS_CHROMEOS)
55 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
56 this);
57 #endif
58 }
59
60 ProcessPowerCollector::~ProcessPowerCollector() {
61 #if defined(OS_CHROMEOS)
62 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
63 this);
64 #endif
65 }
66
67 #if defined(OS_CHROMEOS)
68 void ProcessPowerCollector::PowerChanged(
69 const power_manager::PowerSupplyProperties& prop) {
70 if (prop.battery_state() ==
71 power_manager::PowerSupplyProperties::DISCHARGING) {
72 if (is_initialized_ && !timer_.IsRunning())
73 Initialize();
sky 2014/08/25 19:38:39 Init/Initialize methods are generally one shot fun
Daniel Nishi 2014/08/25 20:19:24 Now in a StartTimer(). I've changed the |is_initi
sky 2014/08/25 20:43:43 This patchset had the Initialize() function. The e
Daniel Nishi 2014/08/25 21:08:33 Initialize() brought back, StartTimer() made priva
74 scale_factor_ = prop.battery_discharge_rate();
75 } else {
76 timer_.Stop();
77 }
78 }
79 #endif
80
81 void ProcessPowerCollector::Initialize() {
82 DCHECK(!timer_.IsRunning());
83 is_initialized_ = true;
84 timer_.Start(FROM_HERE,
85 base::TimeDelta::FromSeconds(kSecondsPerSample),
86 this,
87 &ProcessPowerCollector::HandleUpdateTimeout);
88 }
89
90 double ProcessPowerCollector::UpdatePowerConsumptionForTesting() {
91 return UpdatePowerConsumption();
92 }
93
94 double ProcessPowerCollector::UpdatePowerConsumption() {
95 double total_cpu_percent = SynchronizeProcesses();
96 RecordCpuUsageByOrigin(total_cpu_percent);
97 return total_cpu_percent;
98 }
99
100 void ProcessPowerCollector::HandleUpdateTimeout() {
101 UpdatePowerConsumption();
102 }
103
104 double ProcessPowerCollector::SynchronizeProcesses() {
105 // Update all tabs.
106 for (TabContentsIterator it; !it.done(); it.Next()) {
107 content::RenderProcessHost* render_process = it->GetRenderProcessHost();
108 // Skip incognito web contents.
109 if (render_process->GetBrowserContext()->IsOffTheRecord())
110 continue;
111 UpdateProcessInMap(render_process, it->GetLastCommittedURL().GetOrigin());
112 }
113
114 // Iterate over all profiles to find all app windows to attribute all apps.
115 ProfileManager* pm = g_browser_process->profile_manager();
116 std::vector<Profile*> open_profiles = pm->GetLoadedProfiles();
117 for (std::vector<Profile*>::const_iterator it = open_profiles.begin();
118 it != open_profiles.end();
119 ++it) {
120 const apps::AppWindowRegistry::AppWindowList& app_windows =
121 apps::AppWindowRegistry::Get(*it)->app_windows();
122 for (apps::AppWindowRegistry::AppWindowList::const_iterator itr =
123 app_windows.begin();
124 itr != app_windows.end();
125 ++itr) {
126 content::WebContents* web_contents = (*itr)->web_contents();
127
128 UpdateProcessInMap(web_contents->GetRenderProcessHost(),
129 web_contents->GetLastCommittedURL().GetOrigin());
130 }
131 }
132
133 // Remove invalid processes and sum up the cpu cycle.
134 double total_cpu_percent = 0.0;
135 ProcessMetricsMap::iterator it = metrics_map_.begin();
136 while (it != metrics_map_.end()) {
137 if (!it->second->seen_this_cycle()) {
138 metrics_map_.erase(it++);
139 continue;
140 }
141
142 total_cpu_percent += it->second->last_cpu_percent();
143 it++;
sky 2014/08/25 19:38:40 ++it;
Daniel Nishi 2014/08/25 20:19:24 Done.
Daniel Nishi 2014/08/25 20:19:24 Done.
144 }
145
146 return total_cpu_percent;
147 }
148
149 void ProcessPowerCollector::RecordCpuUsageByOrigin(double total_cpu_percent) {
150 for (ProcessMetricsMap::iterator it = metrics_map_.begin();
sky 2014/08/25 19:38:40 nit: It's a bit weird to do this pass in a functio
Daniel Nishi 2014/08/25 20:19:24 Moved to call site.
151 it != metrics_map_.end();
152 ++it) {
153 // Invalidate the process for the next cycle.
154 it->second->set_seen_this_cycle(false);
155 }
156
157 if (total_cpu_percent <= 0)
sky 2014/08/25 19:38:39 I could see the total being 0, but < 0? Isn't that
Daniel Nishi 2014/08/25 20:19:24 Changed to DCHECKing on less than, return on ==.
158 return;
159
160 for (ProcessMetricsMap::iterator it = metrics_map_.begin();
161 it != metrics_map_.end();
162 ++it) {
163 double last_process_power_usage = it->second->last_cpu_percent();
164 last_process_power_usage *= scale_factor_ / total_cpu_percent;
165
166 GURL origin = it->second->last_origin();
167 power::OriginPowerMap* origin_power_map =
168 power::OriginPowerMapFactory::GetForBrowserContext(
169 it->second->profile());
170 DCHECK(origin_power_map);
171 origin_power_map->AddPowerForOrigin(origin, last_process_power_usage);
172 }
173 }
174
175 void ProcessPowerCollector::UpdateProcessInMap(
176 const content::RenderProcessHost* rph,
177 const GURL& origin) {
178 base::ProcessHandle handle = rph->GetHandle();
179 if (metrics_map_.find(handle) == metrics_map_.end()) {
180 metrics_map_[handle] = linked_ptr<PerProcessData>(new PerProcessData(
181 #if defined(OS_MACOSX)
182 scoped_ptr<base::ProcessMetrics>(
183 base::ProcessMetrics::CreateProcessMetrics(handle, NULL)),
184 #else
185 scoped_ptr<base::ProcessMetrics>(
186 base::ProcessMetrics::CreateProcessMetrics(handle)),
187 #endif
188 origin,
189 Profile::FromBrowserContext(rph->GetBrowserContext())));
190 }
191
192 linked_ptr<PerProcessData>& process_data = metrics_map_[handle];
193 process_data->set_last_cpu_percent(
194 cpu_usage_callback_.is_null() ? process_data->metrics()->GetCPUUsage()
sky 2014/08/25 19:38:40 Is GetCPUUsage an expensive call? Does it do IO or
Daniel Nishi 2014/08/25 20:19:24 It shouldn't be that costly -- in the Linux implem
195 : cpu_usage_callback_.Run(handle));
196 // Skip errors.
197 if (process_data->last_cpu_percent() < 0)
198 process_data->set_last_cpu_percent(0);
sky 2014/08/25 19:38:40 nit: std::max(0, ... on 193 would take care of thi
199 process_data->set_seen_this_cycle(true);
200 }
OLDNEW
« no previous file with comments | « chrome/browser/power/process_power_collector.h ('k') | chrome/browser/power/process_power_collector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698