| OLD | NEW |
| 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 logging | 5 import logging |
| 6 import optparse |
| 6 import os | 7 import os |
| 7 import py_utils | 8 import py_utils |
| 8 import signal | 9 import signal |
| 9 import subprocess | 10 import subprocess |
| 10 import sys | 11 import sys |
| 11 import tempfile | 12 import tempfile |
| 12 | 13 |
| 13 from devil.android import device_temp_file | 14 from devil.android import device_temp_file |
| 14 from devil.android.perf import perf_control | 15 from devil.android.perf import perf_control |
| 15 | 16 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 if not os.stat(perf_profile).st_size: | 87 if not os.stat(perf_profile).st_size: |
| 87 os.remove(perf_profile) | 88 os.remove(perf_profile) |
| 88 self._FailWithLog('Perf recorded a zero-sized file') | 89 self._FailWithLog('Perf recorded a zero-sized file') |
| 89 | 90 |
| 90 self._log_file.close() | 91 self._log_file.close() |
| 91 self._output_file.close() | 92 self._output_file.close() |
| 92 return perf_profile | 93 return perf_profile |
| 93 | 94 |
| 94 | 95 |
| 95 class PerfProfilerAgent(tracing_agents.TracingAgent): | 96 class PerfProfilerAgent(tracing_agents.TracingAgent): |
| 96 def __init__(self, device, categories): | 97 def __init__(self, device): |
| 97 tracing_agents.TracingAgent.__init__(self) | 98 tracing_agents.TracingAgent.__init__(self) |
| 98 self._device = device | 99 self._device = device |
| 99 self._categories = categories | |
| 100 self._perf_binary = self._PrepareDevice(device) | 100 self._perf_binary = self._PrepareDevice(device) |
| 101 self._perf_instance = None | 101 self._perf_instance = None |
| 102 self._categories = None |
| 102 | 103 |
| 103 def __repr__(self): | 104 def __repr__(self): |
| 104 return 'perf profile' | 105 return 'perf profile' |
| 105 | 106 |
| 106 @staticmethod | 107 @staticmethod |
| 107 def IsSupported(): | 108 def IsSupported(): |
| 108 return bool(android_profiling_helper) | 109 return bool(android_profiling_helper) |
| 109 | 110 |
| 110 @staticmethod | 111 @staticmethod |
| 111 def _PrepareDevice(device): | 112 def _PrepareDevice(device): |
| 112 if not 'BUILDTYPE' in os.environ: | 113 if not 'BUILDTYPE' in os.environ: |
| 113 os.environ['BUILDTYPE'] = 'Release' | 114 os.environ['BUILDTYPE'] = 'Release' |
| 114 if binary_manager.NeedsInit(): | 115 if binary_manager.NeedsInit(): |
| 115 binary_manager.InitDependencyManager(None) | 116 binary_manager.InitDependencyManager(None) |
| 116 return android_profiling_helper.PrepareDeviceForPerf(device) | 117 return android_profiling_helper.PrepareDeviceForPerf(device) |
| 117 | 118 |
| 118 @classmethod | 119 @classmethod |
| 119 def GetCategories(cls, device): | 120 def GetCategories(cls, device): |
| 120 perf_binary = cls._PrepareDevice(device) | 121 perf_binary = cls._PrepareDevice(device) |
| 121 return device.RunShellCommand('%s list' % perf_binary) | 122 return device.RunShellCommand('%s list' % perf_binary) |
| 122 | 123 |
| 123 @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) | 124 @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) |
| 124 def StartAgentTracing(self, options, categories, timeout=None): | 125 def StartAgentTracing(self, config, timeout=None): |
| 126 self._categories = _ComputePerfCategories(config) |
| 125 self._perf_instance = _PerfProfiler(self._device, | 127 self._perf_instance = _PerfProfiler(self._device, |
| 126 self._perf_binary, | 128 self._perf_binary, |
| 127 self._categories) | 129 self._categories) |
| 128 | 130 |
| 129 @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) | 131 @py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT) |
| 130 def StopAgentTracing(self, timeout=None): | 132 def StopAgentTracing(self, timeout=None): |
| 131 if not self._perf_instance: | 133 if not self._perf_instance: |
| 132 return | 134 return |
| 133 self._perf_instance.SignalAndWait() | 135 self._perf_instance.SignalAndWait() |
| 134 | 136 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 return None | 199 return None |
| 198 | 200 |
| 199 return json_file_name | 201 return json_file_name |
| 200 | 202 |
| 201 def SupportsExplicitClockSync(self): | 203 def SupportsExplicitClockSync(self): |
| 202 return False | 204 return False |
| 203 | 205 |
| 204 def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback): | 206 def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback): |
| 205 assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be ' | 207 assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be ' |
| 206 'recorded since explicit clock sync is not supported.') | 208 'recorded since explicit clock sync is not supported.') |
| 209 |
| 210 def _OptionalValueCallback(default_value): |
| 211 def callback(option, _, __, parser): # pylint: disable=unused-argument |
| 212 value = default_value |
| 213 if parser.rargs and not parser.rargs[0].startswith('-'): |
| 214 value = parser.rargs.pop(0) |
| 215 setattr(parser.values, option.dest, value) |
| 216 return callback |
| 217 |
| 218 |
| 219 class PerfConfig(tracing_agents.TracingConfig): |
| 220 def __init__(self, perf_categories): |
| 221 tracing_agents.TracingConfig.__init__(self) |
| 222 self.perf_categories = perf_categories |
| 223 |
| 224 |
| 225 def add_options(parser): |
| 226 options = optparse.OptionGroup(parser, 'Perf profiling options') |
| 227 options.add_option('-p', '--perf', help='Capture a perf profile with ' |
| 228 'the chosen comma-delimited event categories. ' |
| 229 'Samples CPU cycles by default. Use "list" to see ' |
| 230 'the available sample types.', action='callback', |
| 231 default='', callback=_OptionalValueCallback('cycles'), |
| 232 metavar='PERF_CATEGORIES', dest='perf_categories') |
| 233 parser.add_option_group(options) |
| 234 return options |
| 235 |
| 236 def get_config(options): |
| 237 return PerfConfig(options.perf_categories) |
| 238 |
| 239 def _ComputePerfCategories(config): |
| 240 if not PerfProfilerAgent.IsSupported(): |
| 241 return [] |
| 242 if not config.perf_categories: |
| 243 return [] |
| 244 return config.perf_categories.split(',') |
| OLD | NEW |