| OLD | NEW | 
|    1 #!/usr/bin/env python |    1 #!/usr/bin/env python | 
|    2 # |    2 # | 
|    3 # Copyright 2013 The Chromium Authors. All rights reserved. |    3 # Copyright 2013 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 import base64 | 
|    7 import gzip |    8 import gzip | 
|    8 import logging |    9 import logging | 
|    9 import optparse |   10 import optparse | 
|   10 import os |   11 import os | 
|   11 import re |   12 import re | 
|   12 import shutil |   13 import shutil | 
|   13 import sys |   14 import sys | 
|   14 import threading |   15 import threading | 
|   15 import time |   16 import time | 
 |   17 import webbrowser | 
|   16 import zipfile |   18 import zipfile | 
|   17 import zlib |   19 import zlib | 
|   18  |   20  | 
|   19 from pylib import android_commands |   21 from pylib import android_commands | 
|   20 from pylib import cmd_helper |   22 from pylib import cmd_helper | 
|   21 from pylib import constants |   23 from pylib import constants | 
|   22 from pylib import pexpect |   24 from pylib import pexpect | 
|   23  |   25  | 
|   24  |   26  | 
 |   27 _TRACE_VIEWER_TEMPLATE = """<!DOCTYPE html> | 
 |   28 <html> | 
 |   29   <head> | 
 |   30     <title>%(title)s</title> | 
 |   31     <style> | 
 |   32       %(timeline_css)s | 
 |   33     </style> | 
 |   34     <style> | 
 |   35       .view { | 
 |   36         overflow: hidden; | 
 |   37         position: absolute; | 
 |   38         top: 0; | 
 |   39         bottom: 0; | 
 |   40         left: 0; | 
 |   41         right: 0; | 
 |   42       } | 
 |   43     </style> | 
 |   44     <script> | 
 |   45       %(timeline_js)s | 
 |   46     </script> | 
 |   47     <script> | 
 |   48       document.addEventListener('DOMContentLoaded', function() { | 
 |   49         var trace_data = window.atob('%(trace_data_base64)s'); | 
 |   50         var m = new tracing.TraceModel(trace_data); | 
 |   51         var timelineViewEl = document.querySelector('.view'); | 
 |   52         ui.decorate(timelineViewEl, tracing.TimelineView); | 
 |   53         timelineViewEl.model = m; | 
 |   54         timelineViewEl.tabIndex = 1; | 
 |   55         timelineViewEl.timeline.focusElement = timelineViewEl; | 
 |   56       }); | 
 |   57     </script> | 
 |   58   </head> | 
 |   59   <body> | 
 |   60     <div class="view"></view> | 
 |   61   </body> | 
 |   62 </html>""" | 
 |   63  | 
|   25 _DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES' |   64 _DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES' | 
|   26  |   65  | 
|   27  |   66  | 
|   28 def _GetTraceTimestamp(): |   67 def _GetTraceTimestamp(): | 
|   29  return time.strftime('%Y-%m-%d-%H%M%S', time.localtime()) |   68  return time.strftime('%Y-%m-%d-%H%M%S', time.localtime()) | 
|   30  |   69  | 
|   31  |   70  | 
 |   71 def _PackageTraceAsHtml(trace_file_name, html_file_name): | 
 |   72   trace_viewer_root = os.path.join(constants.DIR_SOURCE_ROOT, | 
 |   73                                    'third_party', 'trace-viewer') | 
 |   74   build_dir = os.path.join(trace_viewer_root, 'build') | 
 |   75   src_dir = os.path.join(trace_viewer_root, 'src') | 
 |   76   if not build_dir in sys.path: | 
 |   77     sys.path.append(build_dir) | 
 |   78   generate = __import__('generate', {}, {}) | 
 |   79   parse_deps = __import__('parse_deps', {}, {}) | 
 |   80  | 
 |   81   basename = os.path.splitext(trace_file_name)[0] | 
 |   82   load_sequence = parse_deps.calc_load_sequence( | 
 |   83       ['tracing/standalone_timeline_view.js'], [src_dir]) | 
 |   84  | 
 |   85   with open(trace_file_name) as trace_file: | 
 |   86     trace_data = base64.b64encode(trace_file.read()) | 
 |   87     with open(html_file_name, 'w') as html_file: | 
 |   88       html = _TRACE_VIEWER_TEMPLATE % { | 
 |   89         'title': os.path.basename(os.path.splitext(trace_file_name)[0]), | 
 |   90         'timeline_js': generate.generate_js(load_sequence), | 
 |   91         'timeline_css': generate.generate_css(load_sequence), | 
 |   92         'trace_data_base64': trace_data | 
 |   93       } | 
 |   94       html_file.write(html) | 
 |   95  | 
 |   96  | 
|   32 class ChromeTracingController(object): |   97 class ChromeTracingController(object): | 
|   33   def __init__(self, adb, package_info, categories, ring_buffer): |   98   def __init__(self, adb, package_info, categories, ring_buffer): | 
|   34     self._adb = adb |   99     self._adb = adb | 
|   35     self._package_info = package_info |  100     self._package_info = package_info | 
|   36     self._categories = categories |  101     self._categories = categories | 
|   37     self._ring_buffer = ring_buffer |  102     self._ring_buffer = ring_buffer | 
|   38     self._trace_file = None |  103     self._trace_file = None | 
|   39     self._trace_interval = None |  104     self._trace_interval = None | 
|   40     self._trace_start_re = \ |  105     self._trace_start_re = \ | 
|   41        re.compile(r'Logging performance trace to file: (.*)') |  106        re.compile(r'Logging performance trace to file: (.*)') | 
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  201 def _StartTracing(controllers, interval): |  266 def _StartTracing(controllers, interval): | 
|  202   for controller in controllers: |  267   for controller in controllers: | 
|  203     controller.StartTracing(interval) |  268     controller.StartTracing(interval) | 
|  204  |  269  | 
|  205  |  270  | 
|  206 def _StopTracing(controllers): |  271 def _StopTracing(controllers): | 
|  207   for controller in controllers: |  272   for controller in controllers: | 
|  208     controller.StopTracing() |  273     controller.StopTracing() | 
|  209  |  274  | 
|  210  |  275  | 
|  211 def _PullTraces(controllers, output, compress): |  276 def _PullTraces(controllers, output, compress, write_html): | 
|  212   _PrintMessage('Downloading...', eol='') |  277   _PrintMessage('Downloading...', eol='') | 
|  213   trace_files = [] |  278   trace_files = [] | 
|  214   for controller in controllers: |  279   for controller in controllers: | 
|  215     trace_files.append(controller.PullTrace()) |  280     trace_files.append(controller.PullTrace()) | 
|  216  |  281  | 
|  217   if compress and len(trace_files) == 1: |  282   if compress and len(trace_files) == 1: | 
|  218     result = output or trace_files[0] + '.gz' |  283     result = output or trace_files[0] + '.gz' | 
|  219     _CompressFile(trace_files[0], result) |  284     _CompressFile(trace_files[0], result) | 
|  220   elif len(trace_files) > 1: |  285   elif len(trace_files) > 1: | 
|  221     result = output or 'chrome-combined-trace-%s.zip' % _GetTraceTimestamp() |  286     result = output or 'chrome-combined-trace-%s.zip' % _GetTraceTimestamp() | 
|  222     _ArchiveFiles(trace_files, result) |  287     _ArchiveFiles(trace_files, result) | 
|  223   elif output: |  288   elif output: | 
|  224     result = output |  289     result = output | 
|  225     shutil.move(trace_files[0], result) |  290     shutil.move(trace_files[0], result) | 
|  226   else: |  291   else: | 
|  227     result = trace_files[0] |  292     result = trace_files[0] | 
|  228  |  293  | 
 |  294   if write_html: | 
 |  295     result, trace_file = os.path.splitext(result)[0] + '.html', result | 
 |  296     _PackageTraceAsHtml(trace_file, result) | 
 |  297     if trace_file != result: | 
 |  298       os.unlink(trace_file) | 
 |  299  | 
|  229   _PrintMessage('done') |  300   _PrintMessage('done') | 
|  230   _PrintMessage('Trace written to %s' % os.path.abspath(result)) |  301   _PrintMessage('Trace written to %s' % os.path.abspath(result)) | 
 |  302   return result | 
|  231  |  303  | 
|  232  |  304  | 
|  233 def _CaptureAndPullTrace(controllers, interval, output, compress): |  305 def _CaptureAndPullTrace(controllers, interval, output, compress, write_html): | 
|  234   trace_type = ' + '.join(map(str, controllers)) |  306   trace_type = ' + '.join(map(str, controllers)) | 
|  235   try: |  307   try: | 
|  236     _StartTracing(controllers, interval) |  308     _StartTracing(controllers, interval) | 
|  237     if interval: |  309     if interval: | 
|  238       _PrintMessage('Capturing %d-second %s. Press Ctrl-C to stop early...' % \ |  310       _PrintMessage('Capturing %d-second %s. Press Ctrl-C to stop early...' % \ | 
|  239           (interval, trace_type), eol='') |  311           (interval, trace_type), eol='') | 
|  240       time.sleep(interval) |  312       time.sleep(interval) | 
|  241     else: |  313     else: | 
|  242       _PrintMessage('Capturing %s. Press Enter to stop...' % trace_type, eol='') |  314       _PrintMessage('Capturing %s. Press Enter to stop...' % trace_type, eol='') | 
|  243       raw_input() |  315       raw_input() | 
|  244   except KeyboardInterrupt: |  316   except KeyboardInterrupt: | 
|  245     _PrintMessage('\nInterrupted...', eol='') |  317     _PrintMessage('\nInterrupted...', eol='') | 
|  246   finally: |  318   finally: | 
|  247     _StopTracing(controllers) |  319     _StopTracing(controllers) | 
|  248   if interval: |  320   if interval: | 
|  249     _PrintMessage('done') |  321     _PrintMessage('done') | 
|  250  |  322  | 
|  251   _PullTraces(controllers, output, compress) |  323   return _PullTraces(controllers, output, compress, write_html) | 
|  252  |  324  | 
|  253  |  325  | 
|  254 def _ComputeChromeCategories(options): |  326 def _ComputeChromeCategories(options): | 
|  255   categories = [] |  327   categories = [] | 
|  256   if options.trace_cc: |  328   if options.trace_cc: | 
|  257     categories.append('disabled-by-default-cc.debug*') |  329     categories.append('disabled-by-default-cc.debug*') | 
|  258   if options.trace_gpu: |  330   if options.trace_gpu: | 
|  259     categories.append('disabled-by-default-gpu.debug*') |  331     categories.append('disabled-by-default-gpu.debug*') | 
|  260   if options.chrome_categories: |  332   if options.chrome_categories: | 
|  261     categories += options.chrome_categories.split(',') |  333     categories += options.chrome_categories.split(',') | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  304                         'both types of categories. Use "list" to see the ' |  376                         'both types of categories. Use "list" to see the ' | 
|  305                         'available categories. Systrace is disabled by ' |  377                         'available categories. Systrace is disabled by ' | 
|  306                         'default.', metavar='SYS_CATEGORIES', |  378                         'default.', metavar='SYS_CATEGORIES', | 
|  307                         dest='systrace_categories', default='') |  379                         dest='systrace_categories', default='') | 
|  308   categories.add_option('--trace-cc', help='Enable extra trace categories for ' |  380   categories.add_option('--trace-cc', help='Enable extra trace categories for ' | 
|  309                         'compositor frame viewer data.', action='store_true') |  381                         'compositor frame viewer data.', action='store_true') | 
|  310   categories.add_option('--trace-gpu', help='Enable extra trace categories for ' |  382   categories.add_option('--trace-gpu', help='Enable extra trace categories for ' | 
|  311                         'GPU data.', action='store_true') |  383                         'GPU data.', action='store_true') | 
|  312   parser.add_option_group(categories) |  384   parser.add_option_group(categories) | 
|  313  |  385  | 
|  314   parser.add_option('-o', '--output', help='Save profile output to file.') |  386   output_options = optparse.OptionGroup(parser, 'Output options') | 
 |  387   output_options.add_option('-o', '--output', help='Save trace output to file.') | 
 |  388   output_options.add_option('--html', help='Package trace into a standalone ' | 
 |  389                             'html file.', action='store_true') | 
 |  390   output_options.add_option('--view', help='Open resulting trace file in a ' | 
 |  391                             'browser.', action='store_true') | 
 |  392   parser.add_option_group(output_options) | 
 |  393  | 
|  315   browsers = sorted(_GetSupportedBrowsers().keys()) |  394   browsers = sorted(_GetSupportedBrowsers().keys()) | 
|  316   parser.add_option('-b', '--browser', help='Select among installed browsers. ' |  395   parser.add_option('-b', '--browser', help='Select among installed browsers. ' | 
|  317                     'One of ' + ', '.join(browsers) + ', "stable" is used by ' |  396                     'One of ' + ', '.join(browsers) + ', "stable" is used by ' | 
|  318                     'default.', type='choice', choices=browsers, |  397                     'default.', type='choice', choices=browsers, | 
|  319                     default='stable') |  398                     default='stable') | 
|  320   parser.add_option('-v', '--verbose', help='Verbose logging.', |  399   parser.add_option('-v', '--verbose', help='Verbose logging.', | 
|  321                     action='store_true') |  400                     action='store_true') | 
|  322   parser.add_option('-z', '--compress', help='Compress the resulting trace ' |  401   parser.add_option('-z', '--compress', help='Compress the resulting trace ' | 
|  323                     'with gzip. ', action='store_true') |  402                     'with gzip. ', action='store_true') | 
|  324   options, args = parser.parse_args() |  403   options, args = parser.parse_args() | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|  351                                                options.ring_buffer)) |  430                                                options.ring_buffer)) | 
|  352   if systrace_categories: |  431   if systrace_categories: | 
|  353     controllers.append(SystraceController(adb, |  432     controllers.append(SystraceController(adb, | 
|  354                                           systrace_categories, |  433                                           systrace_categories, | 
|  355                                           options.ring_buffer)) |  434                                           options.ring_buffer)) | 
|  356  |  435  | 
|  357   if not controllers: |  436   if not controllers: | 
|  358     _PrintMessage('No trace categories enabled.') |  437     _PrintMessage('No trace categories enabled.') | 
|  359     return 1 |  438     return 1 | 
|  360  |  439  | 
|  361   _CaptureAndPullTrace(controllers, |  440   result = _CaptureAndPullTrace(controllers, | 
|  362                        options.time if not options.continuous else 0, |  441                                 options.time if not options.continuous else 0, | 
|  363                        options.output, |  442                                 options.output, | 
|  364                        options.compress) |  443                                 options.compress, | 
 |  444                                 options.html) | 
 |  445   if options.view: | 
 |  446     webbrowser.open(result) | 
|  365  |  447  | 
|  366  |  448  | 
|  367 if __name__ == '__main__': |  449 if __name__ == '__main__': | 
|  368   sys.exit(main()) |  450   sys.exit(main()) | 
| OLD | NEW |