OLD | NEW |
---|---|
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 """Profiler using data collected from a Monsoon power meter. | 5 """Profiler using data collected from a Monsoon power meter. |
6 | 6 |
7 http://msoon.com/LabEquipment/PowerMonitor/ | 7 http://msoon.com/LabEquipment/PowerMonitor/ |
8 Data collected is a namedtuple of (amps, volts), at 5000 samples/second. | 8 Data collected is a namedtuple of (amps, volts), at 5000 samples/second. |
9 Output graph plots power in watts over time in seconds. | 9 Output graph plots power in watts over time in seconds. |
10 """ | 10 """ |
11 | 11 |
12 import csv | 12 import csv |
13 import multiprocessing | 13 import multiprocessing |
14 | |
15 from telemetry.core import exceptions | 14 from telemetry.core import exceptions |
16 from telemetry.core.platform import profiler | 15 from telemetry.core.platform import profiler |
17 from telemetry.core.platform.profiler import monsoon | 16 from telemetry.core.platform.profiler import monsoon |
17 from telemetry.util import statistics | |
18 | 18 |
19 | 19 |
20 def _CollectData(output_path, is_collecting): | 20 def _CollectData(output_path, is_collecting): |
21 mon = monsoon.Monsoon(wait=False) | 21 mon = monsoon.Monsoon(wait=False) |
22 # Note: Telemetry requires the device to be connected by USB, but that | 22 # Note: Telemetry requires the device to be connected by USB, but that |
23 # puts it in charging mode. This increases the power consumption. | 23 # puts it in charging mode. This increases the power consumption. |
24 mon.SetUsbPassthrough(1) | 24 mon.SetUsbPassthrough(1) |
25 # Nominal Li-ion voltage is 3.7V, but it puts out 4.2V at max capacity. Use | 25 # Nominal Li-ion voltage is 3.7V, but it puts out 4.2V at max capacity. Use |
26 # 4.0V to simulate a "~80%" charged battery. Google "li-ion voltage curve". | 26 # 4.0V to simulate a "~80%" charged battery. Google "li-ion voltage curve". |
27 # This is true only for a single cell. (Most smartphones, some tablets.) | 27 # This is true only for a single cell. (Most smartphones, some tablets.) |
(...skipping 14 matching lines...) Expand all Loading... | |
42 # Add x-axis labels. | 42 # Add x-axis labels. |
43 plot_data = [(i / 5000., sample.amps * sample.volts) | 43 plot_data = [(i / 5000., sample.amps * sample.volts) |
44 for i, sample in enumerate(samples)] | 44 for i, sample in enumerate(samples)] |
45 | 45 |
46 # Print data in csv. | 46 # Print data in csv. |
47 with open(output_path, 'w') as output_file: | 47 with open(output_path, 'w') as output_file: |
48 output_writer = csv.writer(output_file) | 48 output_writer = csv.writer(output_file) |
49 output_writer.writerows(plot_data) | 49 output_writer.writerows(plot_data) |
50 output_file.flush() | 50 output_file.flush() |
51 | 51 |
52 power = [] | |
53 for sample in samples: | |
54 power.append(sample.amps * sample.volts) | |
tonyg
2014/03/12 15:28:38
Neat pythonism:
power_samples = [s.amps * s.volts
| |
55 | |
56 print ('Power total=%f' % statistics.TrapezoidalRule(power, 1/5000.) + | |
tonyg
2014/03/12 15:28:38
I'm wondering whether the labels would be better a
| |
57 ' average=%f' % statistics.ArithmeticMean(power) + | |
58 '+-%f' % statistics.StandardDeviation(power) + | |
59 ' peak=%f' % max(power) + | |
60 ' time=%f' % (len(power) / 5000.)) | |
61 | |
52 print 'To view the Monsoon profile, run:' | 62 print 'To view the Monsoon profile, run:' |
53 print (' echo "set datafile separator \',\'; plot \'%s\' with lines" | ' | 63 print (' echo "set datafile separator \',\'; plot \'%s\' with lines" | ' |
54 'gnuplot --persist' % output_path) | 64 'gnuplot --persist' % output_path) |
55 | 65 |
56 | 66 |
57 class MonsoonProfiler(profiler.Profiler): | 67 class MonsoonProfiler(profiler.Profiler): |
58 def __init__(self, browser_backend, platform_backend, output_path, state): | 68 def __init__(self, browser_backend, platform_backend, output_path, state): |
59 super(MonsoonProfiler, self).__init__( | 69 super(MonsoonProfiler, self).__init__( |
60 browser_backend, platform_backend, output_path, state) | 70 browser_backend, platform_backend, output_path, state) |
61 # We collect the data in a separate process, so we can continuously | 71 # We collect the data in a separate process, so we can continuously |
(...skipping 16 matching lines...) Expand all Loading... | |
78 monsoon.Monsoon(wait=False) | 88 monsoon.Monsoon(wait=False) |
79 except EnvironmentError: | 89 except EnvironmentError: |
80 return False | 90 return False |
81 else: | 91 else: |
82 return True | 92 return True |
83 | 93 |
84 def CollectProfile(self): | 94 def CollectProfile(self): |
85 self._is_collecting.clear() | 95 self._is_collecting.clear() |
86 self._collector.join() | 96 self._collector.join() |
87 return [self._output_path] | 97 return [self._output_path] |
OLD | NEW |