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

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: Comments and fixing some memory issues. 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 delete metrics;
31 }
32
33 ProcessPowerCollector::ProcessPowerCollector()
34 : metrics_map_(new ProcessMetricsMap) {
35 }
36
37 ProcessPowerCollector::~ProcessPowerCollector() {
38 }
39
40 void ProcessPowerCollector::StartUpdating() {
41 DCHECK(!timer_.IsRunning());
42 timer_.Start(FROM_HERE,
43 base::TimeDelta::FromSeconds(kSecondsPerSample),
44 this,
45 &ProcessPowerCollector::UpdatePowerConsumptionCallback);
46 }
47
48 void ProcessPowerCollector::UpdatePowerConsumptionCallback() {
49 UpdateMetricsMap();
50 RecordCpuUsageByOrigin(PopulateCpuUsageByOrigin());
51 }
52
53 void ProcessPowerCollector::UpdateMetricsMap() {
54 // Update all tabs.
55 for (TabContentsIterator it; !it.done(); it.Next()) {
56 content::RenderProcessHost* render_process = it->GetRenderProcessHost();
57 // Skip incognito web contents.
58 if (render_process->GetBrowserContext()->IsOffTheRecord()) {
Daniel Erat 2014/08/18 20:43:04 nit: omit curly brackets
Daniel Nishi 2014/08/19 19:24:20 Done.
59 continue;
60 }
61 AddProcessToMap(render_process, it->GetLastCommittedURL().GetOrigin());
62 }
63
64 // Iterate over all profiles to find all app windows to attribute all apps.
65 ProfileManager* pm = g_browser_process->profile_manager();
66 std::vector<Profile*> open_profiles = pm->GetLoadedProfiles();
67 for (std::vector<Profile*>::const_iterator it = open_profiles.begin();
68 it != open_profiles.end();
69 ++it) {
70 const apps::AppWindowRegistry::AppWindowList& app_windows =
71 apps::AppWindowRegistry::Get(*it)->app_windows();
72 for (apps::AppWindowRegistry::AppWindowList::const_iterator itr =
73 app_windows.begin();
74 itr != app_windows.end();
75 ++itr) {
76 content::WebContents* web_contents = (*itr)->web_contents();
77
78 AddProcessToMap(web_contents->GetRenderProcessHost(),
79 web_contents->GetLastCommittedURL().GetOrigin());
80 }
81 }
82 }
83
84 double ProcessPowerCollector::PopulateCpuUsageByOrigin() {
85 ProcessMetricsMap::iterator it = metrics_map_->begin();
86 double cpu_cycle = 0.0;
87 while (it != metrics_map_->end()) {
88 // If the process doesn't exist anymore, remove it.
89 if (it->second->last_cpu < 0) {
90 metrics_map_->erase(it++);
91 continue;
92 }
93 it->second->last_cpu = it->second->metrics->GetCPUUsage();
94
95 // Skip errors.
96 if (it->second->last_cpu < 0) {
97 it++;
98 continue;
99 }
100
101 cpu_cycle += it->second->last_cpu;
102 it++;
103 }
104
105 return cpu_cycle;
106 }
107
108 void ProcessPowerCollector::RecordCpuUsageByOrigin(double cpu_cycle) {
109 #if defined(OS_CHROMEOS)
110 // Don't record data yet if no power data exists yet.
111 chromeos::PowerDataCollector* power_data_collector =
112 chromeos::PowerDataCollector::Get();
113 if (power_data_collector->power_supply_data().empty())
114 return;
115
116 chromeos::PowerDataCollector::PowerSupplySample sample =
117 power_data_collector->power_supply_data().back();
118
119 // Don't record data if plugged in.
120 if (sample.external_power)
121 return;
122 #endif
123
124 ProcessMetricsMap::iterator it = metrics_map_->begin();
125 while (it != metrics_map_->end()) {
Daniel Erat 2014/08/18 20:43:04 nit: just use a for loop here
Daniel Nishi 2014/08/19 19:24:20 Done.
126 double site_delta = it->second->last_cpu;
Daniel Erat 2014/08/18 20:43:04 please give this variable a better name -- is it r
Daniel Nishi 2014/08/19 19:24:20 On non-CrOS platforms, that's correct. It's scaled
127 #if defined(OS_CHROMEOS)
128 // Only query discharge rate if there is a battery.
129 if (sample.battery_percent > -1 && cpu_cycle > 0)
130 site_delta = site_delta * sample.battery_discharge_rate / cpu_cycle;
131 #endif
132
133 GURL origin = it->second->last_origin;
134 power::OriginPowerMap* origin_power_map =
135 power::OriginPowerMapFactory::GetForBrowserContext(it->second->profile);
136 DCHECK(origin_power_map);
137 origin_power_map->AddPowerForOrigin(origin, site_delta);
138
139 // Invalidate |last_cpu| for the next cycle.
140 it->second->last_cpu = -1;
141 it++;
142 }
143 }
144
145 void ProcessPowerCollector::AddProcessToMap(
146 const content::RenderProcessHost* rph,
147 const GURL& origin) {
148 base::ProcessHandle handle = rph->GetHandle();
149 if (metrics_map_->find(handle) == metrics_map_->end()) {
150 #if defined(OS_MACOSX)
151 (*metrics_map_)[handle] = PerProcessData(
Daniel Erat 2014/08/18 20:43:04 does this even compile on mac? how about restructu
Daniel Nishi 2014/08/19 19:24:20 SGTM. I'm trying to pick up a OS X box, but I'll u
152 base::ProcessMetrics::CreateProcessMetrics(handle, NULL));
153 #else
154 (*metrics_map_)[handle] = linked_ptr<PerProcessData>(
155 new PerProcessData(base::ProcessMetrics::CreateProcessMetrics(handle)));
156 #endif
157 }
158 (*metrics_map_)[handle]->last_origin = origin;
Daniel Erat 2014/08/18 20:43:04 nit: copy the linked_ptr to a local variable so yo
Daniel Nishi 2014/08/19 19:24:20 Is this fine now that most of the lookups have got
159 (*metrics_map_)[handle]->profile =
160 Profile::FromBrowserContext(rph->GetBrowserContext());
161 (*metrics_map_)[handle]->last_cpu = 0;
162 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698