xref: /aosp_15_r20/external/chromium-trace/catapult/systrace/profile_chrome/main.py (revision 1fa4b3da657c0e9ad43c0220bacf9731820715a5)
1*1fa4b3daSHector Dearman#!/usr/bin/env python
2*1fa4b3daSHector Dearman#
3*1fa4b3daSHector Dearman# Copyright 2014 The Chromium Authors. All rights reserved.
4*1fa4b3daSHector Dearman# Use of this source code is governed by a BSD-style license that can be
5*1fa4b3daSHector Dearman# found in the LICENSE file.
6*1fa4b3daSHector Dearman
7*1fa4b3daSHector Dearmanimport logging
8*1fa4b3daSHector Dearmanimport optparse
9*1fa4b3daSHector Dearmanimport os
10*1fa4b3daSHector Dearmanimport sys
11*1fa4b3daSHector Dearmanimport webbrowser
12*1fa4b3daSHector Dearman
13*1fa4b3daSHector Dearmanfrom profile_chrome import chrome_tracing_agent
14*1fa4b3daSHector Dearmanfrom profile_chrome import ddms_tracing_agent
15*1fa4b3daSHector Dearmanfrom profile_chrome import flags
16*1fa4b3daSHector Dearmanfrom profile_chrome import perf_tracing_agent
17*1fa4b3daSHector Dearmanfrom profile_chrome import profiler
18*1fa4b3daSHector Dearmanfrom profile_chrome import ui
19*1fa4b3daSHector Dearmanfrom systrace import util
20*1fa4b3daSHector Dearmanfrom systrace.tracing_agents import atrace_agent
21*1fa4b3daSHector Dearman
22*1fa4b3daSHector Dearmanfrom devil.android import device_utils
23*1fa4b3daSHector Dearmanfrom devil.android.sdk import adb_wrapper
24*1fa4b3daSHector Dearman
25*1fa4b3daSHector Dearman
26*1fa4b3daSHector Dearman_PROFILE_CHROME_AGENT_MODULES = [chrome_tracing_agent, ddms_tracing_agent,
27*1fa4b3daSHector Dearman                                 perf_tracing_agent, atrace_agent]
28*1fa4b3daSHector Dearman
29*1fa4b3daSHector Dearman
30*1fa4b3daSHector Dearmandef _CreateOptionParser():
31*1fa4b3daSHector Dearman  parser = optparse.OptionParser(description='Record about://tracing profiles '
32*1fa4b3daSHector Dearman                                 'from Android browsers. See http://dev.'
33*1fa4b3daSHector Dearman                                 'chromium.org/developers/how-tos/trace-event-'
34*1fa4b3daSHector Dearman                                 'profiling-tool for detailed instructions for '
35*1fa4b3daSHector Dearman                                 'profiling.', conflict_handler='resolve')
36*1fa4b3daSHector Dearman
37*1fa4b3daSHector Dearman  parser = util.get_main_options(parser)
38*1fa4b3daSHector Dearman
39*1fa4b3daSHector Dearman  timed_options = optparse.OptionGroup(parser, 'Timed tracing')
40*1fa4b3daSHector Dearman  timed_options.add_option('-t', '--time', help='Profile for N seconds and '
41*1fa4b3daSHector Dearman                          'download the resulting trace.', metavar='N',
42*1fa4b3daSHector Dearman                           type='float', dest='trace_time')
43*1fa4b3daSHector Dearman  parser.add_option_group(timed_options)
44*1fa4b3daSHector Dearman
45*1fa4b3daSHector Dearman  cont_options = optparse.OptionGroup(parser, 'Continuous tracing')
46*1fa4b3daSHector Dearman  cont_options.add_option('--continuous', help='Profile continuously until '
47*1fa4b3daSHector Dearman                          'stopped.', action='store_true')
48*1fa4b3daSHector Dearman  cont_options.add_option('--ring-buffer', help='Use the trace buffer as a '
49*1fa4b3daSHector Dearman                          'ring buffer and save its contents when stopping '
50*1fa4b3daSHector Dearman                          'instead of appending events into one long trace.',
51*1fa4b3daSHector Dearman                          action='store_true')
52*1fa4b3daSHector Dearman  parser.add_option_group(cont_options)
53*1fa4b3daSHector Dearman
54*1fa4b3daSHector Dearman  parser.add_option_group(flags.OutputOptions(parser))
55*1fa4b3daSHector Dearman
56*1fa4b3daSHector Dearman  browsers = sorted(util.get_supported_browsers().keys())
57*1fa4b3daSHector Dearman  parser.add_option('-b', '--browser', help='Select among installed browsers. '
58*1fa4b3daSHector Dearman                    'One of ' + ', '.join(browsers) + ', "stable" is used by '
59*1fa4b3daSHector Dearman                    'default.', type='choice', choices=browsers,
60*1fa4b3daSHector Dearman                    default='stable')
61*1fa4b3daSHector Dearman  parser.add_option('-v', '--verbose', help='Verbose logging.',
62*1fa4b3daSHector Dearman                    action='store_true')
63*1fa4b3daSHector Dearman  parser.add_option('-z', '--compress', help='Compress the resulting trace '
64*1fa4b3daSHector Dearman                    'with gzip. ', action='store_true')
65*1fa4b3daSHector Dearman
66*1fa4b3daSHector Dearman  # Add options from profile_chrome agents.
67*1fa4b3daSHector Dearman  for module in _PROFILE_CHROME_AGENT_MODULES:
68*1fa4b3daSHector Dearman    parser.add_option_group(module.add_options(parser))
69*1fa4b3daSHector Dearman
70*1fa4b3daSHector Dearman  return parser
71*1fa4b3daSHector Dearman
72*1fa4b3daSHector Dearman
73*1fa4b3daSHector Dearmandef main():
74*1fa4b3daSHector Dearman  parser = _CreateOptionParser()
75*1fa4b3daSHector Dearman  options, _args = parser.parse_args()  # pylint: disable=unused-variable
76*1fa4b3daSHector Dearman  if options.trace_cc:
77*1fa4b3daSHector Dearman    parser.error("""--trace-cc is deprecated.
78*1fa4b3daSHector Dearman
79*1fa4b3daSHector DearmanFor basic jank busting uses, use  --trace-frame-viewer
80*1fa4b3daSHector DearmanFor detailed study of ubercompositor, pass --trace-ubercompositor.
81*1fa4b3daSHector Dearman
82*1fa4b3daSHector DearmanWhen in doubt, just try out --trace-frame-viewer.
83*1fa4b3daSHector Dearman""")
84*1fa4b3daSHector Dearman
85*1fa4b3daSHector Dearman  logging.basicConfig()
86*1fa4b3daSHector Dearman
87*1fa4b3daSHector Dearman  if options.verbose:
88*1fa4b3daSHector Dearman    logging.getLogger().setLevel(logging.DEBUG)
89*1fa4b3daSHector Dearman
90*1fa4b3daSHector Dearman  if not options.device_serial_number:
91*1fa4b3daSHector Dearman    devices = [a.GetDeviceSerial() for a in adb_wrapper.AdbWrapper.Devices()]
92*1fa4b3daSHector Dearman    if len(devices) == 0:
93*1fa4b3daSHector Dearman      raise RuntimeError('No ADB devices connected.')
94*1fa4b3daSHector Dearman    elif len(devices) >= 2:
95*1fa4b3daSHector Dearman      raise RuntimeError('Multiple devices connected, serial number required')
96*1fa4b3daSHector Dearman    options.device_serial_number = devices[0]
97*1fa4b3daSHector Dearman  device = device_utils.DeviceUtils.HealthyDevices(device_arg=
98*1fa4b3daSHector Dearman      options.device_serial_number)[0]
99*1fa4b3daSHector Dearman  package_info = util.get_supported_browsers()[options.browser]
100*1fa4b3daSHector Dearman
101*1fa4b3daSHector Dearman  options.device = device
102*1fa4b3daSHector Dearman  options.package_info = package_info
103*1fa4b3daSHector Dearman
104*1fa4b3daSHector Dearman  # Include Chrome categories by default in profile_chrome.
105*1fa4b3daSHector Dearman  if not options.chrome_categories:
106*1fa4b3daSHector Dearman    options.chrome_categories = chrome_tracing_agent.DEFAULT_CHROME_CATEGORIES
107*1fa4b3daSHector Dearman
108*1fa4b3daSHector Dearman  if options.chrome_categories in ['list', 'help']:
109*1fa4b3daSHector Dearman    ui.PrintMessage('Collecting record categories list...', eol='')
110*1fa4b3daSHector Dearman    record_categories = []
111*1fa4b3daSHector Dearman    disabled_by_default_categories = []
112*1fa4b3daSHector Dearman    record_categories, disabled_by_default_categories = \
113*1fa4b3daSHector Dearman        chrome_tracing_agent.ChromeTracingAgent.GetCategories(
114*1fa4b3daSHector Dearman            device, package_info)
115*1fa4b3daSHector Dearman
116*1fa4b3daSHector Dearman    ui.PrintMessage('done')
117*1fa4b3daSHector Dearman    ui.PrintMessage('Record Categories:')
118*1fa4b3daSHector Dearman    ui.PrintMessage('\n'.join('\t%s' % item \
119*1fa4b3daSHector Dearman        for item in sorted(record_categories)))
120*1fa4b3daSHector Dearman
121*1fa4b3daSHector Dearman    ui.PrintMessage('\nDisabled by Default Categories:')
122*1fa4b3daSHector Dearman    ui.PrintMessage('\n'.join('\t%s' % item \
123*1fa4b3daSHector Dearman        for item in sorted(disabled_by_default_categories)))
124*1fa4b3daSHector Dearman
125*1fa4b3daSHector Dearman    return 0
126*1fa4b3daSHector Dearman
127*1fa4b3daSHector Dearman  if options.atrace_categories in ['list', 'help']:
128*1fa4b3daSHector Dearman    atrace_agent.list_categories(atrace_agent.get_config(options))
129*1fa4b3daSHector Dearman    print '\n'
130*1fa4b3daSHector Dearman    return 0
131*1fa4b3daSHector Dearman
132*1fa4b3daSHector Dearman  if (perf_tracing_agent.PerfProfilerAgent.IsSupported() and
133*1fa4b3daSHector Dearman      options.perf_categories in ['list', 'help']):
134*1fa4b3daSHector Dearman    ui.PrintMessage('\n'.join(
135*1fa4b3daSHector Dearman        perf_tracing_agent.PerfProfilerAgent.GetCategories(device)))
136*1fa4b3daSHector Dearman    return 0
137*1fa4b3daSHector Dearman
138*1fa4b3daSHector Dearman  if not options.trace_time and not options.continuous:
139*1fa4b3daSHector Dearman    ui.PrintMessage('Time interval or continuous tracing should be specified.')
140*1fa4b3daSHector Dearman    return 1
141*1fa4b3daSHector Dearman
142*1fa4b3daSHector Dearman  if (options.chrome_categories and options.atrace_categories and
143*1fa4b3daSHector Dearman      'webview' in options.atrace_categories):
144*1fa4b3daSHector Dearman    logging.warning('Using the "webview" category in atrace together with '
145*1fa4b3daSHector Dearman                    'Chrome tracing results in duplicate trace events.')
146*1fa4b3daSHector Dearman
147*1fa4b3daSHector Dearman  if options.output_file:
148*1fa4b3daSHector Dearman    options.output_file = os.path.expanduser(options.output_file)
149*1fa4b3daSHector Dearman  result = profiler.CaptureProfile(
150*1fa4b3daSHector Dearman      options,
151*1fa4b3daSHector Dearman      options.trace_time if not options.continuous else 0,
152*1fa4b3daSHector Dearman      _PROFILE_CHROME_AGENT_MODULES,
153*1fa4b3daSHector Dearman      output=options.output_file,
154*1fa4b3daSHector Dearman      compress=options.compress,
155*1fa4b3daSHector Dearman      write_json=options.write_json)
156*1fa4b3daSHector Dearman  if options.view:
157*1fa4b3daSHector Dearman    if sys.platform == 'darwin':
158*1fa4b3daSHector Dearman      os.system('/usr/bin/open %s' % os.path.abspath(result))
159*1fa4b3daSHector Dearman    else:
160*1fa4b3daSHector Dearman      webbrowser.open(result)
161