Chromium Code Reviews| 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 |