| 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 | 14 |
| 15 from telemetry.core import exceptions | 15 from telemetry.core import exceptions |
| 16 from telemetry.core.platform import profiler | 16 from telemetry.core.platform import profiler |
| 17 from telemetry.core.platform.profiler import monsoon | 17 from telemetry.core.platform.profiler import monsoon |
| 18 from telemetry.util import statistics |
| 18 | 19 |
| 19 | 20 |
| 20 def _CollectData(output_path, is_collecting): | 21 def _CollectData(output_path, is_collecting): |
| 21 mon = monsoon.Monsoon(wait=False) | 22 mon = monsoon.Monsoon(wait=False) |
| 22 # Note: Telemetry requires the device to be connected by USB, but that | 23 # Note: Telemetry requires the device to be connected by USB, but that |
| 23 # puts it in charging mode. This increases the power consumption. | 24 # puts it in charging mode. This increases the power consumption. |
| 24 mon.SetUsbPassthrough(1) | 25 mon.SetUsbPassthrough(1) |
| 25 # Nominal Li-ion voltage is 3.7V, but it puts out 4.2V at max capacity. Use | 26 # 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". | 27 # 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.) | 28 # This is true only for a single cell. (Most smartphones, some tablets.) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 42 # Add x-axis labels. | 43 # Add x-axis labels. |
| 43 plot_data = [(i / 5000., sample.amps * sample.volts) | 44 plot_data = [(i / 5000., sample.amps * sample.volts) |
| 44 for i, sample in enumerate(samples)] | 45 for i, sample in enumerate(samples)] |
| 45 | 46 |
| 46 # Print data in csv. | 47 # Print data in csv. |
| 47 with open(output_path, 'w') as output_file: | 48 with open(output_path, 'w') as output_file: |
| 48 output_writer = csv.writer(output_file) | 49 output_writer = csv.writer(output_file) |
| 49 output_writer.writerows(plot_data) | 50 output_writer.writerows(plot_data) |
| 50 output_file.flush() | 51 output_file.flush() |
| 51 | 52 |
| 53 power_samples = [s.amps * s.volts for s in samples] |
| 54 |
| 55 print 'Monsoon profile power readings in watts:' |
| 56 print (' Total = %f' % statistics.TrapezoidalRule(power_samples, 1/5000.)) |
| 57 print (' Average = %f' % statistics.ArithmeticMean(power_samples) + |
| 58 '+-%f' % statistics.StandardDeviation(power_samples)) |
| 59 print (' Peak = %f' % max(power_samples)) |
| 60 print (' Duration = %f' % (len(power_samples) / 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 |