Chromium Code Reviews| Index: systrace/systrace/run_systrace.py |
| diff --git a/systrace/systrace/systrace.py b/systrace/systrace/run_systrace.py |
| similarity index 55% |
| rename from systrace/systrace/systrace.py |
| rename to systrace/systrace/run_systrace.py |
| index 738164b69be6ad792a458a3daacea85fda29decb..7c9f5539f71bc8792ca2a378d211650f5c5e82ce 100755 |
| --- a/systrace/systrace/systrace.py |
| +++ b/systrace/systrace/run_systrace.py |
| @@ -1,6 +1,6 @@ |
| #!/usr/bin/env python |
| -# Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +# Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| @@ -10,7 +10,25 @@ This is a tool for capturing a trace that includes data from both userland and |
| the kernel. It creates an HTML file for visualizing the trace. |
| """ |
| +import os |
| import sys |
| +import time |
| +import optparse |
| + |
| +_SYSTRACE_DIR = os.path.abspath( |
| + os.path.join(os.path.dirname(__file__), os.path.pardir)) |
| +_CATAPULT_DIR = os.path.join( |
| + os.path.dirname(os.path.abspath(__file__)), os.path.pardir, os.path.pardir) |
| +_DEVIL_DIR = os.path.join(_CATAPULT_DIR, 'devil') |
| +if _DEVIL_DIR not in sys.path: |
| + sys.path.insert(0, _DEVIL_DIR) |
| +if _SYSTRACE_DIR not in sys.path: |
| + sys.path.insert(0, _SYSTRACE_DIR) |
| + |
| +from devil.utils import cmd_helper |
| +from systrace import systrace_tracing_controller |
| +from systrace.tracing_agents import atrace_agent |
| +from systrace.tracing_agents import ftrace_agent |
| # Make sure we're using a new enough version of Python. |
| # The flags= parameter of re.sub() is new in Python 2.7. And Systrace does not |
| @@ -21,14 +39,6 @@ if version != (2, 7): |
| 'Please use Python 2.7.\n' % version) |
| sys.exit(1) |
| -import imp |
| -import optparse |
| -import os |
| - |
| - |
| -# The default agent directory. |
| -DEFAULT_AGENT_DIR = 'agents' |
| - |
| def parse_options(argv): |
| """Parses and checks the command-line options. |
| @@ -40,9 +50,9 @@ def parse_options(argv): |
| usage = 'Usage: %prog [options] [category1 [category2 ...]]' |
| desc = 'Example: %prog -b 32768 -t 15 gfx input view sched freq' |
| parser = optparse.OptionParser(usage=usage, description=desc) |
| - parser.add_option('-o', dest='output_file', help='write HTML to FILE', |
| - default='trace.html', metavar='FILE') |
| - parser.add_option('-t', '--time', dest='trace_time', type='int', |
| + parser.add_option('-o', dest='output_file', help='write HTML/JSON to FILE', |
| + default=None, metavar='FILE') |
| + parser.add_option('-t', '--time', dest='trace_time', default=0, type='int', |
| help='trace for N seconds', metavar='N') |
| parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int', |
| help='use a trace buffer size of N KB', metavar='N') |
| @@ -50,8 +60,10 @@ def parse_options(argv): |
| help='specify a comma-separated list of kernel functions ' |
| 'to trace') |
| parser.add_option('-l', '--list-categories', dest='list_categories', |
| + default=False, action='store_true') |
| + parser.add_option('-j', '--json', dest='write_json', |
| default=False, action='store_true', |
| - help='list the available categories and exit') |
| + help='write a JSON file') |
| parser.add_option('-a', '--app', dest='app_name', default=None, type='string', |
| action='store', |
| help='enable application-level tracing for comma-separated ' |
| @@ -89,136 +101,67 @@ def parse_options(argv): |
| ' The directories should be comma separated, e.g., ' |
| '--agent-dirs=dir1,dir2,dir3. Directory |%s| is the default' |
| ' agent directory and will always be checked.' |
| - % DEFAULT_AGENT_DIR) |
| + % systrace_tracing_controller.DEFAULT_AGENT_DIR) |
| parser.add_option('--target', dest='target', default='android', type='string', |
| help='chose tracing target (android or linux)') |
| + parser.add_option('--timeout', dest='timeout', type='int', |
| + help='timeout for start and stop tracing (seconds)') |
| + parser.add_option('--collection-timeout', dest='collection_timeout', |
| + type='int', help='timeout for data collection (seconds)') |
| options, categories = parser.parse_args(argv[1:]) |
| + if options.output_file is None: |
| + options.output_file = 'trace.json' if options.write_json else 'trace.html' |
| + |
| if options.link_assets or options.asset_dir != 'trace-viewer': |
| parser.error('--link-assets and --asset-dir are deprecated.') |
| - if (options.trace_time is not None) and (options.trace_time <= 0): |
| - parser.error('the trace time must be a positive number') |
| + if options.trace_time < 0: |
| + parser.error('the trace time must be a non-negative number') |
| if (options.trace_buf_size is not None) and (options.trace_buf_size <= 0): |
| parser.error('the trace buffer size must be a positive number') |
| return (options, categories) |
| - |
| -def write_trace_html(html_filename, script_dir, agents): |
| - """Writes out a trace html file. |
| - |
| - Args: |
| - html_filename: The name of the file to write. |
| - script_dir: The directory containing this script. |
| - agents: The systrace agents. |
| - """ |
| - systrace_dir = os.path.abspath(os.path.dirname(__file__)) |
| - html_prefix = read_asset(systrace_dir, 'prefix.html') |
| - html_suffix = read_asset(systrace_dir, 'suffix.html') |
| - trace_viewer_html = read_asset(script_dir, 'systrace_trace_viewer.html') |
| - |
| - # Open the file in binary mode to prevent python from changing the |
| - # line endings. |
| - html_file = open(html_filename, 'wb') |
| - html_file.write(html_prefix.replace('{{SYSTRACE_TRACE_VIEWER_HTML}}', |
| - trace_viewer_html)) |
| - |
| - html_file.write('<!-- BEGIN TRACE -->\n') |
| - for a in agents: |
| - html_file.write(' <script class="') |
| - html_file.write(a.get_class_name()) |
| - html_file.write('" type="application/text">\n') |
| - html_file.write(a.get_trace_data()) |
| - html_file.write(' </script>\n') |
| - html_file.write('<!-- END TRACE -->\n') |
| - |
| - html_file.write(html_suffix) |
| - html_file.close() |
| - print '\n wrote file://%s\n' % os.path.abspath(html_filename) |
| - |
| - |
| -def create_agents(options, categories): |
| - """Create systrace agents. |
| - |
| - This function will search systrace agent modules in agent directories and |
| - create the corresponding systrace agents. |
| - Args: |
| - options: The command-line options. |
| - categories: The trace categories to capture. |
| - Returns: |
| - The list of systrace agents. |
| - """ |
| - agent_dirs = [os.path.join(os.path.dirname(__file__), DEFAULT_AGENT_DIR)] |
| - if options.agent_dirs: |
| - agent_dirs.extend(options.agent_dirs.split(',')) |
| - |
| - agents = [] |
| - for agent_dir in agent_dirs: |
| - if not agent_dir: |
| - continue |
| - for filename in os.listdir(agent_dir): |
| - (module_name, ext) = os.path.splitext(filename) |
| - if (ext != '.py' or module_name == '__init__' |
| - or module_name.endswith('_unittest')): |
| - continue |
| - (f, pathname, data) = imp.find_module(module_name, [agent_dir]) |
| - try: |
| - module = imp.load_module(module_name, f, pathname, data) |
| - finally: |
| - if f: |
| - f.close() |
| - if module: |
| - agent = module.try_create_agent(options, categories) |
| - if not agent: |
| - continue |
| - agents.append(agent) |
| - return agents |
| - |
| +def get_device_serials(): |
| + cmdout = cmd_helper.GetCmdOutput(['adb', 'devices']) |
| + lines = [x.split() for x in cmdout.splitlines()[1:-1]] |
| + return [x[0] for x in lines if x[1] == 'device'] |
| def main(): |
| options, categories = parse_options(sys.argv) |
| - agents = create_agents(options, categories) |
| - |
| - if not agents: |
| - dirs = DEFAULT_AGENT_DIR |
| - if options.agent_dirs: |
| - dirs += ',' + options.agent_dirs |
| - sys.stderr.write('No systrace agent is available in directories |%s|.\n' % |
| - dirs) |
| - sys.exit(1) |
| - |
| - try: |
| - from . import update_systrace_trace_viewer |
| - except ImportError: |
| - pass |
| - else: |
| - update_systrace_trace_viewer.update() |
| - |
| - for a in agents: |
| - a.start() |
| - |
| - for a in agents: |
| - a.collect_result() |
| - if not a.expect_trace(): |
| - # Nothing more to do. |
| - return |
| - |
| + if options.target == 'android' and not options.device_serial: |
| + devices = get_device_serials() |
| + if len(devices) == 0: |
| + raise RuntimeError('No ADB devices connected.') |
| + elif len(devices) >= 2: |
| + raise RuntimeError('Multiple devices connected, serial number required') |
| + options.device_serial = devices[0] |
| + if options.list_categories: |
| + # Don't do the whole tracing thing; just print the list of categories. |
| + if options.target == 'android': |
| + atrace_agent.list_categories(options) |
| + elif options.target == 'linux': |
| + ftrace_agent.list_categories(options) |
| + return |
| script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) |
|
Zhen Wang
2016/03/29 18:53:39
s/sys.argv[0]/__file__
Change script_dir to be re
alexandermont
2016/03/30 01:04:24
Done.
|
| - write_trace_html(options.output_file, script_dir, agents) |
| - |
| - |
| -def read_asset(src_dir, filename): |
| - return open(os.path.join(src_dir, filename)).read() |
| + controller = systrace_tracing_controller.SystraceTracingController( |
| + script_dir, options, categories) |
| + controller.StartTracing() |
| + if options.from_file is not None: |
| + print 'Reading results from file.' |
| + elif options.trace_time == 0: |
| + raw_input('Starting tracing (stop with enter)') |
| + else: |
| + print 'Starting tracing (%d seconds)' % options.trace_time |
| + time.sleep(options.trace_time) |
| + print 'Tracing completed. Collecting output...' |
| + controller.StopTracing() |
| + print 'Outputting Systrace results...' |
| + controller.OutputSystraceResults(write_json=options.write_json) |
| if __name__ == '__main__' and __package__ is None: |
| - # Add current package to search path. |
| - _SYSTRACE_DIR = os.path.abspath( |
| - os.path.join(os.path.dirname(__file__), os.path.pardir)) |
| - sys.path.insert(0, _SYSTRACE_DIR) |
| - __package__ = "systrace" # pylint: disable=redefined-builtin |
| - |
| main() |