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

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, 4 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 "chrome/browser/chromeos/power/power_data_collector.h"
23 #endif
24
25 namespace {
26 const int kSecondsPerSample = 30;
27 }
28
29 ProcessPowerCollector::PerProcessData::PerProcessData(
30 base::ProcessMetrics* metrics,
31 const GURL& origin,
32 Profile* profile)
33 : metrics_(metrics),
34 profile_(profile),
35 last_origin_(origin),
36 last_cpu_percent_(0) {
37 }
38
39 ProcessPowerCollector::PerProcessData::PerProcessData() {
40 }
41
42 ProcessPowerCollector::PerProcessData::~PerProcessData() {
43 }
44
45 void ProcessPowerCollector::PerProcessData::SetLastCpuPercent(int new_cpu) {
46 last_cpu_percent_ = new_cpu;
47 }
48
49 ProcessPowerCollector::ProcessPowerCollector() {
50 }
51
52 ProcessPowerCollector::~ProcessPowerCollector() {
53 }
54
55 void ProcessPowerCollector::StartUpdating() {
56 DCHECK(!timer_.IsRunning());
57 timer_.Start(FROM_HERE,
58 base::TimeDelta::FromSeconds(kSecondsPerSample),
59 this,
60 &ProcessPowerCollector::UpdatePowerConsumptionCallback);
61 }
62
63 void ProcessPowerCollector::UpdatePowerConsumptionCallback() {
64 UpdateMetricsMap();
65 RecordCpuUsageByOrigin(PopulateCpuUsageByOrigin());
66 }
67
68 void ProcessPowerCollector::UpdateMetricsMap() {
69 // Update all tabs.
70 for (TabContentsIterator it; !it.done(); it.Next()) {
71 content::RenderProcessHost* render_process = it->GetRenderProcessHost();
72 // Skip incognito web contents.
73 if (render_process->GetBrowserContext()->IsOffTheRecord())
74 continue;
75 AddProcessToMap(render_process, it->GetLastCommittedURL().GetOrigin());
76 }
77
78 // Iterate over all profiles to find all app windows to attribute all apps.
79 ProfileManager* pm = g_browser_process->profile_manager();
80 std::vector<Profile*> open_profiles = pm->GetLoadedProfiles();
81 for (std::vector<Profile*>::const_iterator it = open_profiles.begin();
82 it != open_profiles.end();
83 ++it) {
84 const apps::AppWindowRegistry::AppWindowList& app_windows =
85 apps::AppWindowRegistry::Get(*it)->app_windows();
86 for (apps::AppWindowRegistry::AppWindowList::const_iterator itr =
87 app_windows.begin();
88 itr != app_windows.end();
89 ++itr) {
90 content::WebContents* web_contents = (*itr)->web_contents();
91
92 AddProcessToMap(web_contents->GetRenderProcessHost(),
93 web_contents->GetLastCommittedURL().GetOrigin());
94 }
95 }
96 }
97
98 double ProcessPowerCollector::PopulateCpuUsageByOrigin() {
99 ProcessMetricsMap::iterator it = metrics_map_.begin();
100 double cpu_cycle = 0.0;
101 while (it != metrics_map_.end()) {
102 // If the process doesn't exist anymore, remove it.
103 if (it->second->last_cpu_used() < 0) {
Daniel Erat 2014/08/20 00:10:42 should you be doing this after you update the last
Daniel Nishi 2014/08/20 17:16:46 We remove before we query the last percent to avoi
104 metrics_map_.erase(it++);
Daniel Erat 2014/08/20 00:10:42 how about moving the stale-process-clearing to the
105 continue;
106 }
107 it->second->SetLastCpuPercent(it->second->metrics()->GetCPUUsage());
108
109 // Skip errors.
110 if (it->second->last_cpu_used() < 0) {
Daniel Erat 2014/08/20 00:10:42 hmm, so you skip negative usages here. this seems
Daniel Nishi 2014/08/20 17:16:46 Good catch. The intent was to just skip, since the
111 it++;
112 continue;
113 }
114
115 cpu_cycle += it->second->last_cpu_used();
116 it++;
117 }
118
119 return cpu_cycle;
120 }
121
122 void ProcessPowerCollector::RecordCpuUsageByOrigin(double cpu_cycle) {
123 #if defined(OS_CHROMEOS)
124 // Don't record data yet if no power data exists yet.
125 chromeos::PowerDataCollector* power_data_collector =
126 chromeos::PowerDataCollector::Get();
127 if (power_data_collector->power_supply_data().empty())
128 return;
129
130 chromeos::PowerDataCollector::PowerSupplySample sample =
131 power_data_collector->power_supply_data().back();
132
133 // Don't record data if plugged in.
134 if (sample.external_power)
135 return;
136 #endif
137
138 for (ProcessMetricsMap::iterator it = metrics_map_.begin();
139 it != metrics_map_.end();
140 ++it) {
141 double last_process_power_usage = it->second->last_cpu_used();
142 #if defined(OS_CHROMEOS)
143 // Only query discharge rate if there is a battery.
144 if (sample.battery_percent > -1 && cpu_cycle > 0)
145 last_process_power_usage =
146 last_process_power_usage * sample.battery_discharge_rate / cpu_cycle;
147 #endif
148
149 GURL origin = it->second->last_origin();
150 power::OriginPowerMap* origin_power_map =
151 power::OriginPowerMapFactory::GetForBrowserContext(
152 it->second->profile());
153 DCHECK(origin_power_map);
154 origin_power_map->AddPowerForOrigin(origin, last_process_power_usage);
155
156 // Invalidate |last_cpu| for the next cycle.
157 it->second->SetLastCpuPercent(-1);
158 }
159 }
160
161 void ProcessPowerCollector::AddProcessToMap(
162 const content::RenderProcessHost* rph,
163 const GURL& origin) {
164 base::ProcessHandle handle = rph->GetHandle();
165 if (metrics_map_.find(handle) == metrics_map_.end()) {
166 metrics_map_[handle] = linked_ptr<PerProcessData>(new PerProcessData(
167 #if defined(OS_MACOSX)
168 base::ProcessMetrics::CreateProcessMetrics(handle, NULL),
169 #else
170 base::ProcessMetrics::CreateProcessMetrics(handle),
171 #endif
172 origin,
173 Profile::FromBrowserContext(rph->GetBrowserContext())));
174 }
175 // Reset the CPU usage to 0 to signify that the process still exists.
176 metrics_map_[handle]->SetLastCpuPercent(0);
177 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698