Commit 477e91f0 authored by lizeb's avatar lizeb Committed by Commit bot

Add profile_chrome_startup.py to generate combined traces for startup.

This is done following a suggestion in
https://codereview.chromium.org/686413002/.

BUG=361548

Review URL: https://codereview.chromium.org/879853002

Cr-Commit-Position: refs/heads/master@{#313499}
parent d65ea386
# Copyright 2015 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.
import os
import re
import time
from pylib import flag_changer
from pylib.perf import cache_control
from profile_chrome import controllers
class ChromeStartupTracingController(controllers.BaseController):
def __init__(self, device, package_info, cold, url):
self._device = device
self._package_info = package_info
self._cold = cold
self._url = url
self._trace_file = None
self._trace_finish_re = re.compile(r' Completed startup tracing to (.*)')
self._device.old_interface.StartMonitoringLogcat(clear=False)
def __repr__(self):
return 'Browser Startup Trace'
def _SetupTracing(self):
# TODO(lizeb): Figure out how to clean up the command-line file when
# _TearDownTracing() is not executed in StopTracing().
changer = flag_changer.FlagChanger(
self._device, self._package_info.cmdline_file)
changer.AddFlags(['--trace-startup'])
self._device.old_interface.CloseApplication(self._package_info.package)
if self._cold:
self._device.old_interface.EnableAdbRoot()
cache_control.CacheControl(self._device).DropRamCaches()
self._device.old_interface.StartActivity(
package=self._package_info.package,
activity=self._package_info.activity,
data=self._url,
extras={'create_new_tab' : True})
def _TearDownTracing(self):
changer = flag_changer.FlagChanger(
self._device, self._package_info.cmdline_file)
changer.RemoveFlags(['--trace-startup'])
def StartTracing(self, interval):
self._SetupTracing()
self._device.old_interface.SyncLogCat()
def StopTracing(self):
try:
self._trace_file = self._device.old_interface.WaitForLogMatch(
self._trace_finish_re, None, timeout=10).group(1)
finally:
self._TearDownTracing()
def PullTrace(self):
# Wait a bit for the browser to finish writing the trace file.
time.sleep(3)
trace_file = self._trace_file.replace('/storage/emulated/0/', '/sdcard/')
host_file = os.path.join(os.path.curdir, os.path.basename(trace_file))
self._device.PullFile(trace_file, host_file)
return host_file
# Copyright 2015 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.
import os
import json
from profile_chrome import chrome_startup_controller
from profile_chrome import controllers_unittest
class ChromeControllerTest(controllers_unittest.BaseControllerTest):
def testTracing(self):
controller = chrome_startup_controller.ChromeStartupTracingController(
self.device, self.package_info, False, 'https://www.google.com')
interval = 1
try:
controller.StartTracing(interval)
finally:
controller.StopTracing()
result = controller.PullTrace()
try:
with open(result) as f:
json.loads(f.read())
finally:
os.remove(result)
...@@ -18,6 +18,7 @@ class BaseControllerTest(unittest.TestCase): ...@@ -18,6 +18,7 @@ class BaseControllerTest(unittest.TestCase):
self.package_info = profiler.GetSupportedBrowsers()[self.browser] self.package_info = profiler.GetSupportedBrowsers()[self.browser]
self.device = device_utils.DeviceUtils(devices[0]) self.device = device_utils.DeviceUtils(devices[0])
self.device.old_interface.CloseApplication(self.package_info.package)
self.device.StartActivity( self.device.StartActivity(
intent.Intent(activity=self.package_info.activity, intent.Intent(activity=self.package_info.activity,
package=self.package_info.package), package=self.package_info.package),
......
# Copyright 2015 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.
import optparse
def SystraceOptions(parser):
systrace_opts = optparse.OptionGroup(parser, 'Systrace tracing options')
systrace_opts.add_option('-s', '--systrace', help='Capture a systrace with '
'the chosen comma-delimited systrace categories. You'
' can also capture a combined Chrome + systrace by '
'enabling both types of categories. Use "list" to '
'see the available categories. Systrace is disabled '
'by default.', metavar='SYS_CATEGORIES',
dest='systrace_categories', default='')
return systrace_opts
def OutputOptions(parser):
output_options = optparse.OptionGroup(parser, 'Output options')
output_options.add_option('-o', '--output', help='Save trace output to file.')
output_options.add_option('--json', help='Save trace as raw JSON instead of '
'HTML.', action='store_true')
output_options.add_option('--view', help='Open resulting trace file in a '
'browser.', action='store_true')
return output_options
...@@ -11,6 +11,7 @@ import sys ...@@ -11,6 +11,7 @@ import sys
import webbrowser import webbrowser
from profile_chrome import chrome_controller from profile_chrome import chrome_controller
from profile_chrome import flags
from profile_chrome import perf_controller from profile_chrome import perf_controller
from profile_chrome import profiler from profile_chrome import profiler
from profile_chrome import systrace_controller from profile_chrome import systrace_controller
...@@ -119,15 +120,7 @@ def _CreateOptionParser(): ...@@ -119,15 +120,7 @@ def _CreateOptionParser():
action='store_true') action='store_true')
parser.add_option_group(chrome_opts) parser.add_option_group(chrome_opts)
systrace_opts = optparse.OptionGroup(parser, 'Systrace tracing options') parser.add_option_group(flags.SystraceOptions(parser))
systrace_opts.add_option('-s', '--systrace', help='Capture a systrace with '
'the chosen comma-delimited systrace categories. You '
'can also capture a combined Chrome + systrace by '
'enable both types of categories. Use "list" to see '
'the available categories. Systrace is disabled by '
'default.', metavar='SYS_CATEGORIES',
dest='systrace_categories', default='')
parser.add_option_group(systrace_opts)
if perf_controller.PerfProfilerController.IsSupported(): if perf_controller.PerfProfilerController.IsSupported():
perf_opts = optparse.OptionGroup(parser, 'Perf profiling options') perf_opts = optparse.OptionGroup(parser, 'Perf profiling options')
...@@ -139,13 +132,7 @@ def _CreateOptionParser(): ...@@ -139,13 +132,7 @@ def _CreateOptionParser():
metavar='PERF_CATEGORIES', dest='perf_categories') metavar='PERF_CATEGORIES', dest='perf_categories')
parser.add_option_group(perf_opts) parser.add_option_group(perf_opts)
output_options = optparse.OptionGroup(parser, 'Output options') parser.add_option_group(flags.OutputOptions(parser))
output_options.add_option('-o', '--output', help='Save trace output to file.')
output_options.add_option('--json', help='Save trace as raw JSON instead of '
'HTML.', action='store_true')
output_options.add_option('--view', help='Open resulting trace file in a '
'browser.', action='store_true')
parser.add_option_group(output_options)
browsers = sorted(profiler.GetSupportedBrowsers().keys()) browsers = sorted(profiler.GetSupportedBrowsers().keys())
parser.add_option('-b', '--browser', help='Select among installed browsers. ' parser.add_option('-b', '--browser', help='Select among installed browsers. '
......
#!/usr/bin/env python
#
# Copyright 2015 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.
import logging
import optparse
import os
import sys
import webbrowser
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir,
'build', 'android'))
from profile_chrome import chrome_startup_controller
from profile_chrome import controllers
from profile_chrome import flags
from profile_chrome import profiler
from profile_chrome import systrace_controller
from profile_chrome import ui
from pylib import android_commands
from pylib.device import device_utils
def _CreateOptionParser():
parser = optparse.OptionParser(description='Record about://tracing profiles '
'from Android browsers startup, combined with '
'Android systrace. See http://dev.chromium.org'
'/developers/how-tos/trace-event-profiling-'
'tool for detailed instructions for '
'profiling.')
parser.add_option('--url', help='URL to visit on startup. Default: '
'https://www.google.com', default='https://www.google.com',
metavar='URL')
parser.add_option('--cold', help='Flush the OS page cache before starting the'
' browser. Note that this require a device with root '
'access.', default=False, action='store_true')
parser.add_option_group(flags.SystraceOptions(parser))
parser.add_option_group(flags.OutputOptions(parser))
browsers = sorted(profiler.GetSupportedBrowsers().keys())
parser.add_option('-b', '--browser', help='Select among installed browsers. '
'One of ' + ', '.join(browsers) + ', "stable" is used by '
'default.', type='choice', choices=browsers,
default='stable')
parser.add_option('-v', '--verbose', help='Verbose logging.',
action='store_true')
parser.add_option('-z', '--compress', help='Compress the resulting trace '
'with gzip. ', action='store_true')
return parser
def main():
parser = _CreateOptionParser()
options, _ = parser.parse_args()
if options.verbose:
logging.getLogger().setLevel(logging.DEBUG)
devices = android_commands.GetAttachedDevices()
if len(devices) != 1:
logging.error('Exactly 1 device must be attached.')
return 1
device = device_utils.DeviceUtils(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, 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)
if __name__ == '__main__':
sys.exit(main())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment