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 |