Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: systrace/systrace/run_systrace.py

Issue 1776013005: [DO NOT COMMIT] Refactor systrace to support new clock sync design (Closed) Base URL: git@github.com:catapult-project/catapult@master
Patch Set: changes from code review Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
Zhen Wang 2016/03/14 17:11:27 +ccraik, do we need to keep the old file name (sys
alexandermont 2016/03/14 22:19:28 FYI, the reason that I changed the name systrace.p
Zhen Wang 2016/03/16 16:54:29 If you change it to run_systrace.py, you will also
2 2
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2016 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Android system-wide tracing utility. 7 """Android system-wide tracing utility.
8 8
9 This is a tool for capturing a trace that includes data from both userland and 9 This is a tool for capturing a trace that includes data from both userland and
10 the kernel. It creates an HTML file for visualizing the trace. 10 the kernel. It creates an HTML file for visualizing the trace.
11 """ 11 """
12 12
13 import sys 13 import sys
14 import time
15 from devil.utils import cmd_helper
16 from systrace import systrace_tracing_controller
14 17
15 # Make sure we're using a new enough version of Python. 18 # Make sure we're using a new enough version of Python.
16 # The flags= parameter of re.sub() is new in Python 2.7. And Systrace does not 19 # The flags= parameter of re.sub() is new in Python 2.7. And Systrace does not
17 # support Python 3 yet. 20 # support Python 3 yet.
18 version = sys.version_info[:2] 21 version = sys.version_info[:2]
19 if version != (2, 7): 22 if version != (2, 7):
20 sys.stderr.write('This script does not support Python %d.%d. ' 23 sys.stderr.write('This script does not support Python %d.%d. '
21 'Please use Python 2.7.\n' % version) 24 'Please use Python 2.7.\n' % version)
22 sys.exit(1) 25 sys.exit(1)
23 26
24 import imp
25 import optparse 27 import optparse
26 import os 28 import os
27 29
28
29 # The default agent directory.
30 DEFAULT_AGENT_DIR = 'agents'
31
32
33 def parse_options(argv): 30 def parse_options(argv):
34 """Parses and checks the command-line options. 31 """Parses and checks the command-line options.
35 32
36 Returns: 33 Returns:
37 A tuple containing the options structure and a list of categories to 34 A tuple containing the options structure and a list of categories to
38 be traced. 35 be traced.
39 """ 36 """
40 usage = 'Usage: %prog [options] [category1 [category2 ...]]' 37 usage = 'Usage: %prog [options] [category1 [category2 ...]]'
41 desc = 'Example: %prog -b 32768 -t 15 gfx input view sched freq' 38 desc = 'Example: %prog -b 32768 -t 15 gfx input view sched freq'
42 parser = optparse.OptionParser(usage=usage, description=desc) 39 parser = optparse.OptionParser(usage=usage, description=desc)
43 parser.add_option('-o', dest='output_file', help='write HTML to FILE', 40 parser.add_option('-o', dest='output_file', help='write HTML to FILE',
44 default='trace.html', metavar='FILE') 41 default='trace.html', metavar='FILE')
45 parser.add_option('-t', '--time', dest='trace_time', type='int', 42 parser.add_option('-t', '--time', dest='trace_time', type='int',
46 help='trace for N seconds', metavar='N') 43 help='trace for N seconds', metavar='N')
44 parser.add_option('-i', '--interrupt', dest='interrupt', default=False,
Chris Craik 2016/03/12 02:02:34 How would folks feel about making this the default
Zhen Wang 2016/03/14 17:11:27 +1
alexandermont 2016/03/14 22:19:28 Done
45 action='store_true', help='keep tracing until'
46 ' interrupted by user pressing control-C')
47 parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int', 47 parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int',
48 help='use a trace buffer size of N KB', metavar='N') 48 help='use a trace buffer size of N KB', metavar='N')
49 parser.add_option('-k', '--ktrace', dest='kfuncs', action='store', 49 parser.add_option('-k', '--ktrace', dest='kfuncs', action='store',
50 help='specify a comma-separated list of kernel functions ' 50 help='specify a comma-separated list of kernel functions '
51 'to trace') 51 'to trace')
52 parser.add_option('-l', '--list-categories', dest='list_categories', 52 parser.add_option('-l', '--list-categories', dest='list_categories',
53 default=False, action='store_true', 53 default=False, action='store_true',
54 help='list the available categories and exit') 54 help='list the available categories and exit')
55 parser.add_option('-a', '--app', dest='app_name', default=None, type='string', 55 parser.add_option('-a', '--app', dest='app_name', default=None, type='string',
56 action='store', 56 action='store',
(...skipping 25 matching lines...) Expand all
82 'running a live trace') 82 'running a live trace')
83 parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', 83 parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer',
84 type='string', help='(deprecated)') 84 type='string', help='(deprecated)')
85 parser.add_option('-e', '--serial', dest='device_serial', type='string', 85 parser.add_option('-e', '--serial', dest='device_serial', type='string',
86 help='adb device serial number') 86 help='adb device serial number')
87 parser.add_option('--agent-dirs', dest='agent_dirs', type='string', 87 parser.add_option('--agent-dirs', dest='agent_dirs', type='string',
88 help='the directories of additional systrace agent modules.' 88 help='the directories of additional systrace agent modules.'
89 ' The directories should be comma separated, e.g., ' 89 ' The directories should be comma separated, e.g., '
90 '--agent-dirs=dir1,dir2,dir3. Directory |%s| is the default' 90 '--agent-dirs=dir1,dir2,dir3. Directory |%s| is the default'
91 ' agent directory and will always be checked.' 91 ' agent directory and will always be checked.'
92 % DEFAULT_AGENT_DIR) 92 % systrace_tracing_controller.DEFAULT_AGENT_DIR)
93 parser.add_option('--target', dest='target', default='android', type='string', 93 parser.add_option('--target', dest='target', default='android', type='string',
94 help='chose tracing target (android or linux)') 94 help='chose tracing target (android or linux)')
95 95
96 options, categories = parser.parse_args(argv[1:]) 96 options, categories = parser.parse_args(argv[1:])
97 97
98 if options.link_assets or options.asset_dir != 'trace-viewer': 98 if options.link_assets or options.asset_dir != 'trace-viewer':
99 parser.error('--link-assets and --asset-dir are deprecated.') 99 parser.error('--link-assets and --asset-dir are deprecated.')
100 100
101 if (options.trace_time is not None) and (options.trace_time <= 0): 101 if (options.trace_time is not None) and (options.trace_time <= 0):
102 parser.error('the trace time must be a positive number') 102 parser.error('the trace time must be a positive number')
103 103
104 if (options.trace_buf_size is not None) and (options.trace_buf_size <= 0): 104 if (options.trace_buf_size is not None) and (options.trace_buf_size <= 0):
105 parser.error('the trace buffer size must be a positive number') 105 parser.error('the trace buffer size must be a positive number')
106 106
107 return (options, categories) 107 return (options, categories)
108 108
109 109 def get_device_serials():
110 def write_trace_html(html_filename, script_dir, agents): 110 cmdout = cmd_helper.GetCmdOutput(['adb', 'devices'])
111 """Writes out a trace html file. 111 lines = [x.split() for x in cmdout.splitlines()[1:-1]]
112 112 return [x[0] for x in lines if x[1] == 'device']
113 Args:
114 html_filename: The name of the file to write.
115 script_dir: The directory containing this script.
116 agents: The systrace agents.
117 """
118 systrace_dir = os.path.abspath(os.path.dirname(__file__))
119 html_prefix = read_asset(systrace_dir, 'prefix.html')
120 html_suffix = read_asset(systrace_dir, 'suffix.html')
121 trace_viewer_html = read_asset(script_dir, 'systrace_trace_viewer.html')
122
123 # Open the file in binary mode to prevent python from changing the
124 # line endings.
125 html_file = open(html_filename, 'wb')
126 html_file.write(html_prefix.replace('{{SYSTRACE_TRACE_VIEWER_HTML}}',
127 trace_viewer_html))
128
129 html_file.write('<!-- BEGIN TRACE -->\n')
130 for a in agents:
131 html_file.write(' <script class="')
132 html_file.write(a.get_class_name())
133 html_file.write('" type="application/text">\n')
134 html_file.write(a.get_trace_data())
135 html_file.write(' </script>\n')
136 html_file.write('<!-- END TRACE -->\n')
137
138 html_file.write(html_suffix)
139 html_file.close()
140 print '\n wrote file://%s\n' % os.path.abspath(html_filename)
141
142
143 def create_agents(options, categories):
144 """Create systrace agents.
145
146 This function will search systrace agent modules in agent directories and
147 create the corresponding systrace agents.
148 Args:
149 options: The command-line options.
150 categories: The trace categories to capture.
151 Returns:
152 The list of systrace agents.
153 """
154 agent_dirs = [os.path.join(os.path.dirname(__file__), DEFAULT_AGENT_DIR)]
155 if options.agent_dirs:
156 agent_dirs.extend(options.agent_dirs.split(','))
157
158 agents = []
159 for agent_dir in agent_dirs:
160 if not agent_dir:
161 continue
162 for filename in os.listdir(agent_dir):
163 (module_name, ext) = os.path.splitext(filename)
164 if (ext != '.py' or module_name == '__init__'
165 or module_name.endswith('_unittest')):
166 continue
167 (f, pathname, data) = imp.find_module(module_name, [agent_dir])
168 try:
169 module = imp.load_module(module_name, f, pathname, data)
170 finally:
171 if f:
172 f.close()
173 if module:
174 agent = module.try_create_agent(options, categories)
175 if not agent:
176 continue
177 agents.append(agent)
178 return agents
179
180 113
181 def main(): 114 def main():
182 options, categories = parse_options(sys.argv) 115 options, categories = parse_options(sys.argv)
183 agents = create_agents(options, categories) 116 if not options.device_serial:
117 devices = get_device_serials()
118 if len(devices) == 0:
119 raise RuntimeError('No ADB devices connected.')
120 elif len(devices) >= 2:
121 raise RuntimeError('Multiple devices connected, serial number required')
122 options.device_serial = devices[0]
123 script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
124 controller = systrace_tracing_controller.SystraceTracingController(
125 script_dir, options, categories)
126 controller.StartTracing()
127 if options.from_file is not None:
128 print 'Reading results from file.'
129 elif options.interrupt:
130 print 'Starting tracing (stop with control-C)'
131 while True:
132 try:
133 time.sleep(0.5)
134 except KeyboardInterrupt:
135 break
136 else:
137 print 'Starting tracing (%d seconds)' % options.trace_time
138 time.sleep(options.trace_time)
184 139
185 if not agents: 140 print 'Tracing completed. Collecting output...'
186 dirs = DEFAULT_AGENT_DIR 141 controller.StopTracing()
187 if options.agent_dirs: 142 print 'Outputting Systrace results...'
188 dirs += ',' + options.agent_dirs 143 controller.OutputSystraceResults()
189 sys.stderr.write('No systrace agent is available in directories |%s|.\n' %
190 dirs)
191 sys.exit(1)
192
193 try:
194 from . import update_systrace_trace_viewer
195 except ImportError:
196 pass
197 else:
198 update_systrace_trace_viewer.update()
199
200 for a in agents:
201 a.start()
202
203 for a in agents:
204 a.collect_result()
205 if not a.expect_trace():
206 # Nothing more to do.
207 return
208
209 script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
210 write_trace_html(options.output_file, script_dir, agents)
211
212
213 def read_asset(src_dir, filename):
214 return open(os.path.join(src_dir, filename)).read()
215
216 144
217 if __name__ == '__main__' and __package__ is None: 145 if __name__ == '__main__' and __package__ is None:
218 # Add current package to search path. 146 # Add current package to search path.
219 _SYSTRACE_DIR = os.path.abspath( 147 _SYSTRACE_DIR = os.path.abspath(
220 os.path.join(os.path.dirname(__file__), os.path.pardir)) 148 os.path.join(os.path.dirname(__file__), os.path.pardir))
221 sys.path.insert(0, _SYSTRACE_DIR) 149 sys.path.insert(0, _SYSTRACE_DIR)
222 __package__ = "systrace" # pylint: disable=redefined-builtin 150 __package__ = "systrace" # pylint: disable=redefined-builtin
223 151
224 main() 152 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698