def _PullTraces(controllers, output, compress, write_json): ui.PrintMessage('Downloading...', eol='') trace_files = [controller.PullTrace() for controller in controllers] trace_files = [trace for trace in trace_files if trace] if not trace_files: ui.PrintMessage('No results') return '' trace_files = output_generator.MergeTraceFilesIfNeeded(trace_files) if not write_json: print 'Writing trace HTML' html_file = os.path.splitext(trace_files[0])[0] + '.html' trace_results = _PrepareTracesForOutput(trace_files) result = output_generator.GenerateHTMLOutput(trace_results, html_file) print '\nWrote file://%s\n' % result trace_files = [html_file] if compress and len(trace_files) == 1: result = output or trace_files[0] + '.gz' util.CompressFile(trace_files[0], result) elif len(trace_files) > 1: result = (output or 'chrome-combined-trace-%s.zip' % util.GetTraceTimestamp()) util.ArchiveFiles(trace_files, result) elif output: result = output shutil.move(trace_files[0], result) else: result = trace_files[0] return result
def CaptureProfile(options, interval, modules, output=None, compress=False, write_json=False): """Records a profiling trace saves the result to a file. Args: options: Command line options. interval: Time interval to capture in seconds. An interval of None (or 0) continues tracing until stopped by the user. modules: The list of modules to initialize the tracing controller with. output: Output file name or None to use an automatically generated name. compress: If True, the result will be compressed either with gzip or zip depending on the number of captured subtraces. write_json: If True, prefer JSON output over HTML. Returns: Path to saved profile. """ agents_with_config = tracing_controller.CreateAgentsWithConfig( options, modules) if chrome_startup_tracing_agent in modules: controller_config = tracing_controller.GetChromeStartupControllerConfig( options) else: controller_config = tracing_controller.GetControllerConfig(options) controller = tracing_controller.TracingController(agents_with_config, controller_config) try: result = controller.StartTracing() trace_type = controller.GetTraceType() if not result: ui.PrintMessage('Trace starting failed.') if interval: ui.PrintMessage( ('Capturing %d-second %s. Press Enter to stop early...' % (interval, trace_type)), eol='') ui.WaitForEnter(interval) else: ui.PrintMessage('Capturing %s. Press Enter to stop...' % trace_type, eol='') raw_input() ui.PrintMessage('Stopping...') all_results = controller.StopTracing() finally: if interval: ui.PrintMessage('done') return _GetResults(all_results, controller, output, compress, write_json, interval)
def _PullTraces(controllers, output, compress, write_json): ui.PrintMessage('Downloading...', eol='') trace_files = [controller.PullTrace() for controller in controllers] trace_files = [trace for trace in trace_files if trace] if not trace_files: ui.PrintMessage('No results') return [] result = trace_packager.PackageTraces(trace_files, output=output, compress=compress, write_json=write_json) ui.PrintMessage('done') ui.PrintMessage('Trace written to file://%s' % os.path.abspath(result)) return result
def PullTrace(self): symfs_dir = os.path.join(tempfile.gettempdir(), os.path.expandvars('$USER-perf-symfs')) if not os.path.exists(symfs_dir): os.makedirs(symfs_dir) required_libs = set() # Download the recorded perf profile. perf_profile = self._perf_instance.PullResult(symfs_dir) required_libs = \ android_profiling_helper.GetRequiredLibrariesForPerfProfile( perf_profile) if not required_libs: logging.warning( 'No libraries required by perf trace. Most likely there ' 'are no samples in the trace.') # Build a symfs with all the necessary libraries. kallsyms = android_profiling_helper.CreateSymFs(self._device, symfs_dir, required_libs, use_symlinks=False) perfhost_path = binary_manager.FetchPath( android_profiling_helper.GetPerfhostName(), 'x86_64', 'linux') ui.PrintMessage('\nNote: to view the profile in perf, run:') ui.PrintMessage(' ' + self._GetInteractivePerfCommand( perfhost_path, perf_profile, symfs_dir, required_libs, kallsyms)) # Convert the perf profile into JSON. perf_script_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'third_party', 'perf_to_tracing.py') json_file_name = os.path.basename(perf_profile) with open(os.devnull, 'w') as dev_null, \ open(json_file_name, 'w') as json_file: cmd = [ perfhost_path, 'script', '-s', perf_script_path, '-i', perf_profile, '--symfs', symfs_dir, '--kallsyms', kallsyms ] if subprocess.call(cmd, stdout=json_file, stderr=dev_null): logging.warning( 'Perf data to JSON conversion failed. The result will ' 'not contain any perf samples. You can still view the ' 'perf data manually as shown above.') return None return json_file_name
def _GetResults(trace_results, controller, output, compress, write_json, interval): ui.PrintMessage('Downloading...') # Wait for the trace file to get written. time.sleep(1) for agent in controller.get_child_agents: if isinstance(agent, chrome_tracing_agent.ChromeTracingAgent): time.sleep(interval / 4) # Ignore the systraceController because it will not contain any results, # instead being in charge of collecting results. trace_results = [ x for x in controller.all_results if not (x.source_name == 'systraceController') ] if not trace_results: ui.PrintMessage('No results') return '' result = None trace_results = output_generator.MergeTraceResultsIfNeeded(trace_results) if not write_json: ui.PrintMessage('Writing trace HTML...') html_file = output or trace_results[0].source_name + '.html' result = output_generator.GenerateHTMLOutput(trace_results, html_file) ui.PrintMessage('\nWrote file://%s' % result) elif compress and len(trace_results) == 1: result = output or trace_results[0].source_name + '.gz' util.WriteDataToCompressedFile(trace_results[0].raw_data, result) elif len(trace_results) > 1: result = (output or 'chrome-combined-trace-%s.zip' % util.GetTraceTimestamp()) util.ArchiveData(trace_results, result) elif output: result = output with open(result, 'wb') as f: f.write(trace_results[0].raw_data) else: result = trace_results[0].source_name with open(result, 'wb') as f: f.write(trace_results[0].raw_data) return result
def _GetResults(agents, output, compress, write_json, interval): ui.PrintMessage('Downloading...', eol='') # Wait for the trace file to get written. time.sleep(1) trace_results = [] for agent in agents: if isinstance(agent, chrome_tracing_agent.ChromeTracingAgent): time.sleep(interval / 4) trace_results.append(agent.GetResults()) if not trace_results: ui.PrintMessage('No results') return '' result = None trace_results = output_generator.MergeTraceResultsIfNeeded(trace_results) if not write_json: print 'Writing trace HTML' html_file = trace_results[0].source_name + '.html' result = output_generator.GenerateHTMLOutput(trace_results, html_file) print '\nWrote file://%s\n' % result elif compress and len(trace_results) == 1: result = output or trace_results[0].source_name + '.gz' util.WriteDataToCompressedFile(trace_results[0].raw_data, result) elif len(trace_results) > 1: result = (output or 'chrome-combined-trace-%s.zip' % util.GetTraceTimestamp()) util.ArchiveData(trace_results, result) elif output: result = output with open(result, 'wb') as f: f.write(trace_results[0].raw_data) else: result = trace_results[0].source_name with open(result, 'wb') as f: f.write(trace_results[0].raw_data) return result
def CaptureProfile(agents, interval, output=None, compress=False, write_json=False): """Records a profiling trace saves the result to a file. Args: agents: List of tracing agents. interval: Time interval to capture in seconds. An interval of None (or 0) continues tracing until stopped by the user. output: Output file name or None to use an automatically generated name. compress: If True, the result will be compressed either with gzip or zip depending on the number of captured subtraces. write_json: If True, prefer JSON output over HTML. Returns: Path to saved profile. """ trace_type = ' + '.join(map(str, agents)) try: _StartTracing(agents) if interval: ui.PrintMessage( ('Capturing %d-second %s. Press Enter to stop early...' % (interval, trace_type)), eol='') ui.WaitForEnter(interval) else: ui.PrintMessage('Capturing %s. Press Enter to stop...' % trace_type, eol='') raw_input() finally: _StopTracing(agents) if interval: ui.PrintMessage('done') return _GetResults(agents, output, compress, write_json, interval)
def main(): parser = _CreateOptionParser() options, _ = parser.parse_args() if options.verbose: logging.getLogger().setLevel(logging.DEBUG) devices = device_utils.DeviceUtils.HealthyDevices() if len(devices) != 1: logging.error('Exactly 1 device must be attached.') return 1 device = devices[0] package_info = profiler.GetSupportedBrowsers()[options.browser] if options.systrace_categories in ['list', 'help']: ui.PrintMessage('\n'.join( systrace_controller.SystraceController.GetCategories(device))) return 0 systrace_categories = (options.systrace_categories.split(',') if options.systrace_categories else []) enabled_controllers = [] # Enable the systrace and chrome controller. The systrace controller should go # first because otherwise the resulting traces miss early systrace data. if systrace_categories: enabled_controllers.append( systrace_controller.SystraceController(device, systrace_categories, False)) enabled_controllers.append( chrome_startup_controller.ChromeStartupTracingController( device, package_info, options.cold, options.url)) if options.output: options.output = os.path.expanduser(options.output) result = profiler.CaptureProfile(enabled_controllers, options.time, output=options.output, compress=options.compress, write_json=options.json) if options.view: if sys.platform == 'darwin': os.system('/usr/bin/open %s' % os.path.abspath(result)) else: webbrowser.open(result)
def main(): parser = _CreateOptionParser() options, _args = parser.parse_args() # pylint: disable=unused-variable if options.trace_cc: parser.error("""--trace-cc is deprecated. For basic jank busting uses, use --trace-frame-viewer For detailed study of ubercompositor, pass --trace-ubercompositor. When in doubt, just try out --trace-frame-viewer. """) if options.verbose: logging.getLogger().setLevel(logging.DEBUG) if not options.device_serial_number: devices = [ a.GetDeviceSerial() for a in adb_wrapper.AdbWrapper.Devices() ] 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_number = devices[0] device = device_utils.DeviceUtils.HealthyDevices( device_arg=options.device_serial_number)[0] package_info = util.get_supported_browsers()[options.browser] options.device = device options.package_info = package_info # Include Chrome categories by default in profile_chrome. if not options.chrome_categories: options.chrome_categories = chrome_tracing_agent.DEFAULT_CHROME_CATEGORIES if options.chrome_categories in ['list', 'help']: ui.PrintMessage('Collecting record categories list...', eol='') record_categories = [] disabled_by_default_categories = [] record_categories, disabled_by_default_categories = \ chrome_tracing_agent.ChromeTracingAgent.GetCategories( device, package_info) ui.PrintMessage('done') ui.PrintMessage('Record Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(record_categories))) ui.PrintMessage('\nDisabled by Default Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(disabled_by_default_categories))) return 0 if options.atrace_categories in ['list', 'help']: atrace_agent.list_categories(atrace_agent.get_config(options)) print '\n' return 0 if (perf_tracing_agent.PerfProfilerAgent.IsSupported() and options.perf_categories in ['list', 'help']): ui.PrintMessage('\n'.join( perf_tracing_agent.PerfProfilerAgent.GetCategories(device))) return 0 if not options.trace_time and not options.continuous: ui.PrintMessage( 'Time interval or continuous tracing should be specified.') return 1 if (options.chrome_categories and options.atrace_categories and 'webview' in options.atrace_categories): logging.warning('Using the "webview" category in atrace together with ' 'Chrome tracing results in duplicate trace events.') if options.output_file: options.output_file = os.path.expanduser(options.output_file) result = profiler.CaptureProfile( options, options.trace_time if not options.continuous else 0, _PROFILE_CHROME_AGENT_MODULES, output=options.output_file, compress=options.compress, write_json=options.write_json) if options.view: if sys.platform == 'darwin': os.system('/usr/bin/open %s' % os.path.abspath(result)) else: webbrowser.open(result)
def main(): parser = _CreateOptionParser() options, _args = parser.parse_args() if options.trace_cc: parser.parse_error("""--trace-cc is deprecated. For basic jank busting uses, use --trace-frame-viewer For detailed study of ubercompositor, pass --trace-ubercompositor. When in doubt, just try out --trace-frame-viewer. """) if options.verbose: logging.getLogger().setLevel(logging.DEBUG) devices = device_utils.DeviceUtils.HealthyDevices() device = None if options.device: device = next((d for d in devices if d == options.device), None) elif len(devices) == 1: device = devices[0] if not device: parser.error('Use -d/--device to select a device:\n' + '\n'.join(devices)) package_info = profiler.GetSupportedBrowsers()[options.browser] if options.chrome_categories in ['list', 'help']: ui.PrintMessage('Collecting record categories list...', eol='') record_categories = [] disabled_by_default_categories = [] record_categories, disabled_by_default_categories = \ chrome_controller.ChromeTracingController.GetCategories( device, package_info) ui.PrintMessage('done') ui.PrintMessage('Record Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(record_categories))) ui.PrintMessage('\nDisabled by Default Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(disabled_by_default_categories))) return 0 if options.systrace_categories in ['list', 'help']: ui.PrintMessage('\n'.join( systrace_controller.SystraceController.GetCategories(device))) return 0 if (perf_controller.PerfProfilerController.IsSupported() and options.perf_categories in ['list', 'help']): ui.PrintMessage('\n'.join( perf_controller.PerfProfilerController.GetCategories(device))) return 0 if not options.time and not options.continuous: ui.PrintMessage( 'Time interval or continuous tracing should be specified.') return 1 chrome_categories = _ComputeChromeCategories(options) systrace_categories = _ComputeSystraceCategories(options) perf_categories = _ComputePerfCategories(options) if chrome_categories and 'webview' in systrace_categories: logging.warning( 'Using the "webview" category in systrace together with ' 'Chrome tracing results in duplicate trace events.') enabled_controllers = [] if chrome_categories: enabled_controllers.append( chrome_controller.ChromeTracingController(device, package_info, chrome_categories, options.ring_buffer, options.trace_memory)) if systrace_categories: enabled_controllers.append( systrace_controller.SystraceController(device, systrace_categories, options.ring_buffer)) if perf_categories: enabled_controllers.append( perf_controller.PerfProfilerController(device, perf_categories)) if options.ddms: enabled_controllers.append( ddms_controller.DdmsController(device, package_info)) if not enabled_controllers: ui.PrintMessage('No trace categories enabled.') return 1 if options.output: options.output = os.path.expanduser(options.output) result = profiler.CaptureProfile( enabled_controllers, options.time if not options.continuous else 0, output=options.output, compress=options.compress, write_json=options.json) if options.view: if sys.platform == 'darwin': os.system('/usr/bin/open %s' % os.path.abspath(result)) else: webbrowser.open(result)
def main(): parser = _CreateOptionParser() options, _args = parser.parse_args() # pylint: disable=unused-variable if options.trace_cc: parser.error("""--trace-cc is deprecated. For basic jank busting uses, use --trace-frame-viewer For detailed study of ubercompositor, pass --trace-ubercompositor. When in doubt, just try out --trace-frame-viewer. """) if options.verbose: logging.getLogger().setLevel(logging.DEBUG) device = device_utils.DeviceUtils.HealthyDevices( device_arg=options.device_serial_number)[0] package_info = profiler.GetSupportedBrowsers()[options.browser] options.device = device options.package_info = package_info # Add options that are present in Systrace but not in profile_chrome (since # they both use the same tracing controller). # TODO(washingtonp): Once Systrace uses all of the profile_chrome agents, # manually setting these options will no longer be necessary and should be # removed. options.list_categories = None options.link_assets = None options.asset_dir = None options.timeout = None options.collection_timeout = None options.target = None if options.chrome_categories in ['list', 'help']: ui.PrintMessage('Collecting record categories list...', eol='') record_categories = [] disabled_by_default_categories = [] record_categories, disabled_by_default_categories = \ chrome_tracing_agent.ChromeTracingAgent.GetCategories( device, package_info) ui.PrintMessage('done') ui.PrintMessage('Record Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(record_categories))) ui.PrintMessage('\nDisabled by Default Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(disabled_by_default_categories))) return 0 if options.atrace_categories in ['list', 'help']: ui.PrintMessage('\n'.join( atrace_tracing_agent.AtraceAgent.GetCategories(device))) return 0 if (perf_tracing_agent.PerfProfilerAgent.IsSupported() and options.perf_categories in ['list', 'help']): ui.PrintMessage('\n'.join( perf_tracing_agent.PerfProfilerAgent.GetCategories(device))) return 0 if not options.trace_time and not options.continuous: ui.PrintMessage( 'Time interval or continuous tracing should be specified.') return 1 if options.chrome_categories and 'webview' in options.atrace_categories: logging.warning('Using the "webview" category in atrace together with ' 'Chrome tracing results in duplicate trace events.') if options.output_file: options.output_file = os.path.expanduser(options.output_file) result = profiler.CaptureProfile( options, options.trace_time if not options.continuous else 0, _PROFILE_CHROME_AGENT_MODULES, output=options.output_file, compress=options.compress, write_json=options.write_json) if options.view: if sys.platform == 'darwin': os.system('/usr/bin/open %s' % os.path.abspath(result)) else: webbrowser.open(result)
def main(): parser = _CreateOptionParser() options, _args = parser.parse_args() if options.trace_cc: parser.parse_error("""--trace-cc is deprecated. For basic jank busting uses, use --trace-frame-viewer For detailed study of ubercompositor, pass --trace-ubercompositor. When in doubt, just try out --trace-frame-viewer. """) if options.verbose: logging.getLogger().setLevel(logging.DEBUG) devices = android_commands.GetAttachedDevices() if len(devices) != 1: parser.error('Exactly 1 device must be attached.') device = device_utils.DeviceUtils(devices[0]) package_info = profiler.GetSupportedBrowsers()[options.browser] if options.chrome_categories in ['list', 'help']: ui.PrintMessage('Collecting record categories list...', eol='') record_categories = [] disabled_by_default_categories = [] record_categories, disabled_by_default_categories = \ chrome_controller.ChromeTracingController.GetCategories( device, package_info) ui.PrintMessage('done') ui.PrintMessage('Record Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(record_categories))) ui.PrintMessage('\nDisabled by Default Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(disabled_by_default_categories))) return 0 if options.systrace_categories in ['list', 'help']: ui.PrintMessage('\n'.join( systrace_controller.SystraceController.GetCategories(device))) return 0 if (perf_controller.PerfProfilerController.IsSupported() and options.perf_categories in ['list', 'help']): ui.PrintMessage('\n'.join( perf_controller.PerfProfilerController.GetCategories(device))) return 0 if not options.time and not options.continuous: ui.PrintMessage( 'Time interval or continuous tracing should be specified.') return 1 chrome_categories = _ComputeChromeCategories(options) systrace_categories = _ComputeSystraceCategories(options) perf_categories = _ComputePerfCategories(options) if chrome_categories and 'webview' in systrace_categories: logging.warning( 'Using the "webview" category in systrace together with ' 'Chrome tracing results in duplicate trace events.') enabled_controllers = [] if chrome_categories: enabled_controllers.append( chrome_controller.ChromeTracingController(device, package_info, chrome_categories, options.ring_buffer, options.trace_memory)) if systrace_categories: enabled_controllers.append( systrace_controller.SystraceController(device, systrace_categories, options.ring_buffer)) if perf_categories: enabled_controllers.append( perf_controller.PerfProfilerController(device, perf_categories)) if not enabled_controllers: ui.PrintMessage('No trace categories enabled.') return 1 if options.output: options.output = os.path.expanduser(options.output) result = profiler.CaptureProfile( enabled_controllers, options.time if not options.continuous else 0, output=options.output, compress=options.compress, write_json=options.json) if options.view_canary: if sys.platform == 'darwin': os.system(( '/usr/bin/open -a /Applications/Google\ Chrome\ Canary.app %s ' '--args --enable-impl-side-painting --enable-skia-benchmarking ' '--allow-webui-compositing') % os.path.abspath(result)) else: _PrintMessage( 'No Chrome Canary on this platform to open trace in, try a different view method' ) elif options.view: if sys.platform == 'darwin': os.system('/usr/bin/open %s' % os.path.abspath(result)) else: webbrowser.open(result) elif options.run_tev and result: os.system('trace-event-viewer %s' % result)
elif len(devices) >= 2: raise RuntimeError('Multiple devices connected, serial number required') options.device_serial_number = devices[0] presentation.device = device_utils.DeviceUtils.HealthyDevices(device_arg= options.device_serial_number)[0] package_info = util.get_supported_browsers()[options.browser] options.presentation.device = presentation.device options.package_info = package_info # Include Chrome categories by default in profile_chrome. if not options.chrome_categories: options.chrome_categories = chrome_tracing_agent.DEFAULT_CHROME_CATEGORIES if options.chrome_categories in ['list', 'help']: ui.PrintMessage('Collecting record categories list...', eol='') record_categories = [] disabled_by_default_categories = [] record_categories, disabled_by_default_categories = \ chrome_tracing_agent.ChromeTracingAgent.GetCategories( presentation.device, package_info) ui.PrintMessage('done') ui.PrintMessage('Record Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(record_categories))) ui.PrintMessage('\nDisabled by Default Categories:') ui.PrintMessage('\n'.join('\t%s' % item \ for item in sorted(disabled_by_default_categories)))