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

Side by Side Diff: tools/perf/metrics/power.py

Issue 350763005: [Telemetry] Power metric: subtract quiescent power draw from result (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unit tests Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « tools/perf/measurements/webrtc.py ('k') | tools/telemetry/telemetry/core/platform/__init__.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import time
6
5 from metrics import Metric 7 from metrics import Metric
6 from telemetry.value import scalar 8 from telemetry.value import scalar
7 9
10
8 class PowerMetric(Metric): 11 class PowerMetric(Metric):
9 """A metric for measuring power usage.""" 12 """A metric for measuring power usage."""
10 13
11 def __init__(self): 14 def __init__(self, browser, quiescent_measurement_time_s=0):
15 """PowerMetric Constructor.
16
17 Args:
18 browser: browser object to use.
19 quiescent_measurement_time_s: time to measure quiescent power,
20 in seconds. 0 means don't measure quiescent power."""
12 super(PowerMetric, self).__init__() 21 super(PowerMetric, self).__init__()
13 self._browser = None 22 self._browser = browser
14 self._running = False 23 self._running = False
15 self._starting_cpu_stats = None 24 self._starting_cpu_stats = None
16 self._results = None 25 self._results = None
26 self._quiescent_power_draw_mwh = 0
27 self._MeasureQuiescentPower(quiescent_measurement_time_s)
17 28
18 def __del__(self): 29 def __del__(self):
19 # TODO(jeremy): Remove once crbug.com/350841 is fixed. 30 # TODO(jeremy): Remove once crbug.com/350841 is fixed.
20 # Don't leave power monitoring processes running on the system. 31 # Don't leave power monitoring processes running on the system.
21 self._StopInternal() 32 self._StopInternal()
22 parent = super(PowerMetric, self) 33 parent = super(PowerMetric, self)
23 if hasattr(parent, '__del__'): 34 if hasattr(parent, '__del__'):
24 parent.__del__() 35 parent.__del__()
25 36
26 def _StopInternal(self): 37 def _StopInternal(self):
27 """ Stop monitoring power if measurement is running. This function is 38 """Stop monitoring power if measurement is running. This function is
28 idempotent.""" 39 idempotent."""
29 if not self._running: 40 if not self._running:
30 return 41 return
31 self._running = False 42 self._running = False
32 self._results = self._browser.platform.StopMonitoringPower() 43 self._results = self._browser.platform.StopMonitoringPower()
33 if self._results: # StopMonitoringPower() can return None. 44 if self._results: # StopMonitoringPower() can return None.
34 self._results['cpu_stats'] = ( 45 self._results['cpu_stats'] = (
35 _SubtractCpuStats(self._browser.cpu_stats, self._starting_cpu_stats)) 46 _SubtractCpuStats(self._browser.cpu_stats, self._starting_cpu_stats))
36 47
48 def _MeasureQuiescentPower(self, measurement_time_s):
49 """Measure quiescent power draw for the system."""
50 platform = self._browser.platform
51 if not platform.CanMonitorPower() or \
52 platform.CanMeasurePerApplicationPower() or \
53 not measurement_time_s:
54 return
55
56 platform.StartMonitoringPower(self._browser)
57 time.sleep(measurement_time_s)
58 power_results = platform.StopMonitoringPower()
59 self._quiescent_power_draw_mwh = (
60 power_results.get('energy_consumption_mwh', 0))
61
37 def Start(self, _, tab): 62 def Start(self, _, tab):
38 if not tab.browser.platform.CanMonitorPower(): 63 if not tab.browser.platform.CanMonitorPower():
39 return 64 return
40 65
41 self._results = None 66 self._results = None
42 self._browser = tab.browser
43 self._StopInternal() 67 self._StopInternal()
44 68
45 # This line invokes top a few times, call before starting power measurement. 69 # This line invokes top a few times, call before starting power measurement.
46 self._starting_cpu_stats = self._browser.cpu_stats 70 self._starting_cpu_stats = self._browser.cpu_stats
47 self._browser.platform.StartMonitoringPower(self._browser) 71 self._browser.platform.StartMonitoringPower(self._browser)
48 self._running = True 72 self._running = True
49 73
50 def Stop(self, _, tab): 74 def Stop(self, _, tab):
51 if not tab.browser.platform.CanMonitorPower(): 75 if not tab.browser.platform.CanMonitorPower():
52 return 76 return
53 77
54 self._StopInternal() 78 self._StopInternal()
55 79
56 def AddResults(self, _, results): 80 def AddResults(self, _, results):
57 """Add the collected power data into the results object. 81 """Add the collected power data into the results object.
58 82
59 This function needs to be robust in the face of differing power data on 83 This function needs to be robust in the face of differing power data on
60 various platforms. Therefore data existence needs to be checked when 84 various platforms. Therefore data existence needs to be checked when
61 building up the results. Additionally 0 is a valid value for many of the 85 building up the results. Additionally 0 is a valid value for many of the
62 metrics here which is why there are plenty of checks for 'is not None' 86 metrics here which is why there are plenty of checks for 'is not None'
63 below. 87 below.
64 """ 88 """
65 if not self._results: 89 if not self._results:
66 return 90 return
67 91
68 energy_consumption_mwh = self._results.get('energy_consumption_mwh') 92 application_energy_consumption_mwh = (
69 if energy_consumption_mwh is not None: 93 self._results.get('application_energy_consumption_mwh'))
94 total_energy_consumption_mwh = self._results.get('energy_consumption_mwh')
95
96 if not application_energy_consumption_mwh and total_energy_consumption_mwh:
97 application_energy_consumption_mwh = max(
98 total_energy_consumption_mwh - self._quiescent_power_draw_mwh, 0)
99
100 if total_energy_consumption_mwh is not None:
70 results.AddValue(scalar.ScalarValue( 101 results.AddValue(scalar.ScalarValue(
71 results.current_page, 'energy_consumption_mwh', 'mWh', 102 results.current_page, 'energy_consumption_mwh', 'mWh',
72 energy_consumption_mwh)) 103 total_energy_consumption_mwh))
104
105 if application_energy_consumption_mwh is not None:
106 results.AddValue(scalar.ScalarValue(
107 results.current_page, 'application_energy_consumption_mwh', 'mWh',
108 application_energy_consumption_mwh))
73 109
74 component_utilization = self._results.get('component_utilization', {}) 110 component_utilization = self._results.get('component_utilization', {})
75 # GPU Frequency. 111 # GPU Frequency.
76 gpu_power = component_utilization.get('gpu', {}) 112 gpu_power = component_utilization.get('gpu', {})
77 gpu_freq_hz = gpu_power.get('average_frequency_hz') 113 gpu_freq_hz = gpu_power.get('average_frequency_hz')
78 if gpu_freq_hz is not None: 114 if gpu_freq_hz is not None:
79 results.AddValue(scalar.ScalarValue( 115 results.AddValue(scalar.ScalarValue(
80 results.current_page, 'gpu_average_frequency_hz', 'hz', gpu_freq_hz, 116 results.current_page, 'gpu_average_frequency_hz', 'hz', gpu_freq_hz,
81 important=False)) 117 important=False))
82 118
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 if (not cpu_stats[process_type]) or (not start_cpu_stats[process_type]): 150 if (not cpu_stats[process_type]) or (not start_cpu_stats[process_type]):
115 continue 151 continue
116 # Skip if IdleWakeupCount is not present. 152 # Skip if IdleWakeupCount is not present.
117 if (('IdleWakeupCount' not in cpu_stats[process_type]) or 153 if (('IdleWakeupCount' not in cpu_stats[process_type]) or
118 ('IdleWakeupCount' not in start_cpu_stats[process_type])): 154 ('IdleWakeupCount' not in start_cpu_stats[process_type])):
119 continue 155 continue
120 idle_wakeup_delta = (cpu_stats[process_type]['IdleWakeupCount'] - 156 idle_wakeup_delta = (cpu_stats[process_type]['IdleWakeupCount'] -
121 start_cpu_stats[process_type]['IdleWakeupCount']) 157 start_cpu_stats[process_type]['IdleWakeupCount'])
122 cpu_delta[process_type] = idle_wakeup_delta 158 cpu_delta[process_type] = idle_wakeup_delta
123 return cpu_delta 159 return cpu_delta
OLDNEW
« no previous file with comments | « tools/perf/measurements/webrtc.py ('k') | tools/telemetry/telemetry/core/platform/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698