Home | History | Annotate | Download | only in bin
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2015 The Chromium Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 import logging
      8 import optparse
      9 import os
     10 import sys
     11 import webbrowser
     12 
     13 _SYSTRACE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
     14 sys.path.append(_SYSTRACE_DIR)
     15 
     16 from profile_chrome import chrome_startup_controller
     17 from profile_chrome import controllers
     18 from profile_chrome import flags
     19 from profile_chrome import profiler
     20 from profile_chrome import systrace_controller
     21 from profile_chrome import ui
     22 
     23 _CATAPULT_DIR = os.path.join(
     24     os.path.dirname(os.path.abspath(__file__)), '..', '..')
     25 sys.path.append(os.path.join(_CATAPULT_DIR, 'devil'))
     26 
     27 from devil.android import device_utils
     28 
     29 
     30 def _CreateOptionParser():
     31   parser = optparse.OptionParser(description='Record about://tracing profiles '
     32                                  'from Android browsers startup, combined with '
     33                                  'Android systrace. See http://dev.chromium.org'
     34                                  '/developers/how-tos/trace-event-profiling-'
     35                                  'tool for detailed instructions for '
     36                                  'profiling.')
     37   parser.add_option('--url', help='URL to visit on startup. Default: '
     38                     'https://www.google.com. An empty URL launches Chrome with'
     39                     ' a MAIN action instead of VIEW.',
     40                     default='https://www.google.com', metavar='URL')
     41   parser.add_option('--cold', help='Flush the OS page cache before starting the'
     42                     ' browser. Note that this require a device with root '
     43                     'access.', default=False, action='store_true')
     44   parser.add_option_group(flags.SystraceOptions(parser))
     45   parser.add_option_group(flags.OutputOptions(parser))
     46 
     47   browsers = sorted(profiler.GetSupportedBrowsers().keys())
     48   parser.add_option('-b', '--browser', help='Select among installed browsers. '
     49                     'One of ' + ', '.join(browsers) + ', "stable" is used by '
     50                     'default.', type='choice', choices=browsers,
     51                     default='stable')
     52   parser.add_option('-v', '--verbose', help='Verbose logging.',
     53                     action='store_true')
     54   parser.add_option('-z', '--compress', help='Compress the resulting trace '
     55                     'with gzip. ', action='store_true')
     56   parser.add_option('-t', '--time', help='Stops tracing after N seconds, 0 to '
     57                     'manually stop (startup trace ends after at most 5s).',
     58                     default=5, metavar='N', type='int')
     59   return parser
     60 
     61 
     62 def main():
     63   parser = _CreateOptionParser()
     64   options, _ = parser.parse_args()
     65 
     66   if options.verbose:
     67     logging.getLogger().setLevel(logging.DEBUG)
     68 
     69   devices = device_utils.DeviceUtils.HealthyDevices()
     70   if len(devices) != 1:
     71     logging.error('Exactly 1 device must be attached.')
     72     return 1
     73   device = devices[0]
     74   package_info = profiler.GetSupportedBrowsers()[options.browser]
     75 
     76   if options.systrace_categories in ['list', 'help']:
     77     ui.PrintMessage('\n'.join(
     78         systrace_controller.SystraceController.GetCategories(device)))
     79     return 0
     80   systrace_categories = (options.systrace_categories.split(',')
     81                          if options.systrace_categories else [])
     82   enabled_controllers = []
     83   # Enable the systrace and chrome controller. The systrace controller should go
     84   # first because otherwise the resulting traces miss early systrace data.
     85   if systrace_categories:
     86     enabled_controllers.append(systrace_controller.SystraceController(
     87         device, systrace_categories, False))
     88   enabled_controllers.append(
     89       chrome_startup_controller.ChromeStartupTracingController(
     90           device, package_info, options.cold, options.url))
     91   if options.output:
     92     options.output = os.path.expanduser(options.output)
     93   result = profiler.CaptureProfile(enabled_controllers,
     94                                    options.time,
     95                                    output=options.output,
     96                                    compress=options.compress,
     97                                    write_json=options.json)
     98   if options.view:
     99     if sys.platform == 'darwin':
    100       os.system('/usr/bin/open %s' % os.path.abspath(result))
    101     else:
    102       webbrowser.open(result)
    103 
    104 
    105 if __name__ == '__main__':
    106   sys.exit(main())
    107