summaryrefslogtreecommitdiffstats
path: root/build
diff options
context:
space:
mode:
authorskyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 16:27:27 +0000
committerskyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 16:27:27 +0000
commitc0921404fb62d69359d9b6551acb3567a4c33ba0 (patch)
tree6d1aebe7426f214fd4479cda0e66b692e77cc6ef /build
parent908431e63848edfd99d78ec0cec0277bbea6e48a (diff)
downloadchromium_src-c0921404fb62d69359d9b6551acb3567a4c33ba0.zip
chromium_src-c0921404fb62d69359d9b6551acb3567a4c33ba0.tar.gz
chromium_src-c0921404fb62d69359d9b6551acb3567a4c33ba0.tar.bz2
Move adb_profile_chrome under tools/android/
Move adb_profile_chrome from build/android/ to tools/android/ to make its purpose clearer. BUG=375754 TEST=tools/android/adb_profile_chrome/run_tests Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=276779 Review URL: https://codereview.chromium.org/310413003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277031 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build')
-rwxr-xr-xbuild/android/adb_profile_chrome2
-rwxr-xr-xbuild/android/adb_profile_chrome.py13
-rw-r--r--build/android/chrome_profiler/__init__.py3
-rw-r--r--build/android/chrome_profiler/chrome_controller.py102
-rw-r--r--build/android/chrome_profiler/chrome_controller_unittest.py46
-rw-r--r--build/android/chrome_profiler/controllers.py16
-rw-r--r--build/android/chrome_profiler/controllers_unittest.py23
-rwxr-xr-xbuild/android/chrome_profiler/main.py250
-rw-r--r--build/android/chrome_profiler/perf_controller.py186
-rw-r--r--build/android/chrome_profiler/perf_controller_unittest.py38
-rw-r--r--build/android/chrome_profiler/profiler.py83
-rw-r--r--build/android/chrome_profiler/profiler_unittest.py78
-rwxr-xr-xbuild/android/chrome_profiler/run_tests3
-rw-r--r--build/android/chrome_profiler/systrace_controller.py95
-rw-r--r--build/android/chrome_profiler/systrace_controller_unittest.py36
-rw-r--r--build/android/chrome_profiler/trace_packager.py94
-rw-r--r--build/android/chrome_profiler/trace_packager_unittest.py35
-rw-r--r--build/android/chrome_profiler/ui.py25
-rw-r--r--build/android/chrome_profiler/util.py8
19 files changed, 1 insertions, 1135 deletions
diff --git a/build/android/adb_profile_chrome b/build/android/adb_profile_chrome
index 00b1199..ee6f940 100755
--- a/build/android/adb_profile_chrome
+++ b/build/android/adb_profile_chrome
@@ -5,4 +5,4 @@
# found in the LICENSE file.
#
# Start / stop profiling in chrome.
-exec $(dirname $0)/adb_profile_chrome.py $@
+exec $(dirname $0)/../../tools/android/adb_profile_chrome.py $@
diff --git a/build/android/adb_profile_chrome.py b/build/android/adb_profile_chrome.py
deleted file mode 100755
index 0270a62..0000000
--- a/build/android/adb_profile_chrome.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2013 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 sys
-
-from chrome_profiler import main
-
-
-if __name__ == '__main__':
- sys.exit(main.main())
diff --git a/build/android/chrome_profiler/__init__.py b/build/android/chrome_profiler/__init__.py
deleted file mode 100644
index 4d6aabb..0000000
--- a/build/android/chrome_profiler/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# Copyright 2014 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.
diff --git a/build/android/chrome_profiler/chrome_controller.py b/build/android/chrome_profiler/chrome_controller.py
deleted file mode 100644
index 745e5d7..0000000
--- a/build/android/chrome_profiler/chrome_controller.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright 2014 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 json
-import os
-import re
-import time
-
-from chrome_profiler import controllers
-
-from pylib import pexpect
-
-_HEAP_PROFILE_MMAP_PROPERTY = 'heapprof.mmap'
-
-class ChromeTracingController(controllers.BaseController):
- def __init__(self, device, package_info,
- categories, ring_buffer, trace_memory=False):
- controllers.BaseController.__init__(self)
- self._device = device
- self._package_info = package_info
- self._categories = categories
- self._ring_buffer = ring_buffer
- self._trace_file = None
- self._trace_interval = None
- self._trace_memory = trace_memory
- self._trace_start_re = \
- re.compile(r'Logging performance trace to file')
- self._trace_finish_re = \
- re.compile(r'Profiler finished[.] Results are in (.*)[.]')
- self._device.old_interface.StartMonitoringLogcat(clear=False)
-
- def __repr__(self):
- return 'chrome trace'
-
- @staticmethod
- def GetCategories(device, package_info):
- device.old_interface.BroadcastIntent(
- package_info.package, 'GPU_PROFILER_LIST_CATEGORIES')
- try:
- json_category_list = device.old_interface.WaitForLogMatch(
- re.compile(r'{"traceCategoriesList(.*)'), None, timeout=5).group(0)
- except pexpect.TIMEOUT:
- raise RuntimeError('Performance trace category list marker not found. '
- 'Is the correct version of the browser running?')
-
- record_categories = []
- disabled_by_default_categories = []
- json_data = json.loads(json_category_list)['traceCategoriesList']
- for item in json_data:
- if item.startswith('disabled-by-default'):
- disabled_by_default_categories.append(item)
- else:
- record_categories.append(item)
-
- return record_categories, disabled_by_default_categories
-
- def StartTracing(self, interval):
- self._trace_interval = interval
- self._device.old_interface.SyncLogCat()
- self._device.old_interface.BroadcastIntent(
- self._package_info.package, 'GPU_PROFILER_START',
- '-e categories "%s"' % ','.join(self._categories),
- '-e continuous' if self._ring_buffer else '')
-
- if self._trace_memory:
- self._device.old_interface.EnableAdbRoot()
- self._device.old_interface.system_properties \
- [_HEAP_PROFILE_MMAP_PROPERTY] = 1
-
- # Chrome logs two different messages related to tracing:
- #
- # 1. "Logging performance trace to file"
- # 2. "Profiler finished. Results are in [...]"
- #
- # The first one is printed when tracing starts and the second one indicates
- # that the trace file is ready to be pulled.
- try:
- self._device.old_interface.WaitForLogMatch(
- self._trace_start_re, None, timeout=5)
- except pexpect.TIMEOUT:
- raise RuntimeError('Trace start marker not found. Is the correct version '
- 'of the browser running?')
-
- def StopTracing(self):
- self._device.old_interface.BroadcastIntent(
- self._package_info.package,
- 'GPU_PROFILER_STOP')
- self._trace_file = self._device.old_interface.WaitForLogMatch(
- self._trace_finish_re, None, timeout=120).group(1)
- if self._trace_memory:
- self._device.old_interface.system_properties \
- [_HEAP_PROFILE_MMAP_PROPERTY] = 0
-
- def PullTrace(self):
- # Wait a bit for the browser to finish writing the trace file.
- time.sleep(self._trace_interval / 4 + 1)
-
- 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.old_interface.PullFileFromDevice(trace_file, host_file)
- return host_file
diff --git a/build/android/chrome_profiler/chrome_controller_unittest.py b/build/android/chrome_profiler/chrome_controller_unittest.py
deleted file mode 100644
index e8c2829..0000000
--- a/build/android/chrome_profiler/chrome_controller_unittest.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2014 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 chrome_profiler import chrome_controller
-from chrome_profiler import controllers_unittest
-
-
-class ChromeControllerTest(controllers_unittest.BaseControllerTest):
- def testGetCategories(self):
- # Not supported on stable yet.
- # TODO(skyostil): Remove this once category queries roll into stable.
- if self.browser == 'stable':
- return
-
- categories = \
- chrome_controller.ChromeTracingController.GetCategories(
- self.device, self.package_info)
-
- self.assertEquals(len(categories), 2)
- self.assertTrue(categories[0])
- self.assertTrue(categories[1])
-
- def testTracing(self):
- categories = '*'
- ring_buffer = False
- controller = chrome_controller.ChromeTracingController(self.device,
- self.package_info,
- categories,
- ring_buffer)
-
- 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)
diff --git a/build/android/chrome_profiler/controllers.py b/build/android/chrome_profiler/controllers.py
deleted file mode 100644
index a569dbc..0000000
--- a/build/android/chrome_profiler/controllers.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2014 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 exceptions
-
-# pylint: disable=R0201
-class BaseController(object):
- def StartTracing(self, _):
- raise exceptions.NotImplementError
-
- def StopTracing(self):
- raise exceptions.NotImplementError
-
- def PullTrace(self):
- raise exceptions.NotImplementError
diff --git a/build/android/chrome_profiler/controllers_unittest.py b/build/android/chrome_profiler/controllers_unittest.py
deleted file mode 100644
index c2b6a41..0000000
--- a/build/android/chrome_profiler/controllers_unittest.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2014 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 unittest
-
-from chrome_profiler import profiler
-
-from pylib import android_commands
-from pylib.device import device_utils
-
-
-class BaseControllerTest(unittest.TestCase):
- def setUp(self):
- devices = android_commands.GetAttachedDevices()
- self.browser = 'stable'
- self.package_info = profiler.GetSupportedBrowsers()[self.browser]
- self.device = device_utils.DeviceUtils(devices[0])
-
- adb = android_commands.AndroidCommands(devices[0])
- adb.StartActivity(self.package_info.package,
- self.package_info.activity,
- wait_for_completion=True)
diff --git a/build/android/chrome_profiler/main.py b/build/android/chrome_profiler/main.py
deleted file mode 100755
index 729163f..0000000
--- a/build/android/chrome_profiler/main.py
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2014 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
-
-from chrome_profiler import chrome_controller
-from chrome_profiler import perf_controller
-from chrome_profiler import profiler
-from chrome_profiler import systrace_controller
-from chrome_profiler import ui
-
-from pylib import android_commands
-from pylib.device import device_utils
-
-
-_DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES'
-
-
-def _ComputeChromeCategories(options):
- categories = []
- if options.trace_frame_viewer:
- categories.append('disabled-by-default-cc.debug')
- if options.trace_ubercompositor:
- categories.append('disabled-by-default-cc.debug*')
- if options.trace_gpu:
- categories.append('disabled-by-default-gpu.debug*')
- if options.trace_flow:
- categories.append('disabled-by-default-toplevel.flow')
- if options.trace_memory:
- categories.append('disabled-by-default-memory')
- if options.chrome_categories:
- categories += options.chrome_categories.split(',')
- return categories
-
-
-def _ComputeSystraceCategories(options):
- if not options.systrace_categories:
- return []
- return options.systrace_categories.split(',')
-
-
-def _ComputePerfCategories(options):
- if not options.perf_categories:
- return []
- return options.perf_categories.split(',')
-
-
-def _OptionalValueCallback(default_value):
- def callback(option, _, __, parser):
- value = default_value
- if parser.rargs and not parser.rargs[0].startswith('-'):
- value = parser.rargs.pop(0)
- setattr(parser.values, option.dest, value)
- return callback
-
-
-def _CreateOptionParser():
- parser = optparse.OptionParser(description='Record about://tracing profiles '
- 'from Android browsers. See http://dev.'
- 'chromium.org/developers/how-tos/trace-event-'
- 'profiling-tool for detailed instructions for '
- 'profiling.')
-
- timed_options = optparse.OptionGroup(parser, 'Timed tracing')
- timed_options.add_option('-t', '--time', help='Profile for N seconds and '
- 'download the resulting trace.', metavar='N',
- type='float')
- parser.add_option_group(timed_options)
-
- cont_options = optparse.OptionGroup(parser, 'Continuous tracing')
- cont_options.add_option('--continuous', help='Profile continuously until '
- 'stopped.', action='store_true')
- cont_options.add_option('--ring-buffer', help='Use the trace buffer as a '
- 'ring buffer and save its contents when stopping '
- 'instead of appending events into one long trace.',
- action='store_true')
- parser.add_option_group(cont_options)
-
- chrome_opts = optparse.OptionGroup(parser, 'Chrome tracing options')
- chrome_opts.add_option('-c', '--categories', help='Select Chrome tracing '
- 'categories with comma-delimited wildcards, '
- 'e.g., "*", "cat1*,-cat1a". Omit this option to trace '
- 'Chrome\'s default categories. Chrome tracing can be '
- 'disabled with "--categories=\'\'". Use "list" to '
- 'see the available categories.',
- metavar='CHROME_CATEGORIES', dest='chrome_categories',
- default=_DEFAULT_CHROME_CATEGORIES)
- chrome_opts.add_option('--trace-cc',
- help='Deprecated, use --trace-frame-viewer.',
- action='store_true')
- chrome_opts.add_option('--trace-frame-viewer',
- help='Enable enough trace categories for '
- 'compositor frame viewing.', action='store_true')
- chrome_opts.add_option('--trace-ubercompositor',
- help='Enable enough trace categories for '
- 'ubercompositor frame data.', action='store_true')
- chrome_opts.add_option('--trace-gpu', help='Enable extra trace categories '
- 'for GPU data.', action='store_true')
- chrome_opts.add_option('--trace-flow', help='Enable extra trace categories '
- 'for IPC message flows.', action='store_true')
- chrome_opts.add_option('--trace-memory', help='Enable extra trace categories '
- 'for memory profile. (tcmalloc required)',
- action='store_true')
- parser.add_option_group(chrome_opts)
-
- 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 '
- '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():
- perf_opts = optparse.OptionGroup(parser, 'Perf profiling options')
- perf_opts.add_option('-p', '--perf', help='Capture a perf profile with '
- 'the chosen comma-delimited event categories. '
- 'Samples CPU cycles by default. Use "list" to see '
- 'the available sample types.', action='callback',
- default='', callback=_OptionalValueCallback('cycles'),
- metavar='PERF_CATEGORIES', dest='perf_categories')
- parser.add_option_group(perf_opts)
-
- 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')
- parser.add_option_group(output_options)
-
- 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, _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 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:
- if sys.platform == 'darwin':
- os.system('/usr/bin/open %s' % os.path.abspath(result))
- else:
- webbrowser.open(result)
diff --git a/build/android/chrome_profiler/perf_controller.py b/build/android/chrome_profiler/perf_controller.py
deleted file mode 100644
index ba4b572..0000000
--- a/build/android/chrome_profiler/perf_controller.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2014 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 os
-import subprocess
-import sys
-import tempfile
-
-from chrome_profiler import controllers
-from chrome_profiler import ui
-
-from pylib import android_commands
-from pylib import constants
-from pylib.perf import perf_control
-
-sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT,
- 'tools',
- 'telemetry'))
-try:
- # pylint: disable=F0401
- from telemetry.core.platform.profiler import android_profiling_helper
- from telemetry.util import support_binaries
-except ImportError:
- android_profiling_helper = None
- support_binaries = None
-
-
-_PERF_OPTIONS = [
- # Sample across all processes and CPUs to so that the current CPU gets
- # recorded to each sample.
- '--all-cpus',
- # In perf 3.13 --call-graph requires an argument, so use the -g short-hand
- # which does not.
- '-g',
- # Increase priority to avoid dropping samples. Requires root.
- '--realtime', '80',
- # Record raw samples to get CPU information.
- '--raw-samples',
- # Increase sampling frequency for better coverage.
- '--freq', '2000',
-]
-
-
-class _PerfProfiler(object):
- def __init__(self, device, perf_binary, categories):
- self._device = device
- self._output_file = android_commands.DeviceTempFile(
- self._device.old_interface, prefix='perf_output')
- self._log_file = tempfile.TemporaryFile()
-
- device_param = (['-s', self._device.old_interface.GetDevice()]
- if self._device.old_interface.GetDevice() else [])
- cmd = ['adb'] + device_param + \
- ['shell', perf_binary, 'record',
- '--output', self._output_file.name] + _PERF_OPTIONS
- if categories:
- cmd += ['--event', ','.join(categories)]
- self._perf_control = perf_control.PerfControl(self._device)
- self._perf_control.ForceAllCpusOnline(True)
- self._perf_process = subprocess.Popen(cmd,
- stdout=self._log_file,
- stderr=subprocess.STDOUT)
-
- def SignalAndWait(self):
- perf_pids = self._device.old_interface.ExtractPid('perf')
- self._device.old_interface.RunShellCommand(
- 'kill -SIGINT ' + ' '.join(perf_pids))
- self._perf_process.wait()
- self._perf_control.ForceAllCpusOnline(False)
-
- def _FailWithLog(self, msg):
- self._log_file.seek(0)
- log = self._log_file.read()
- raise RuntimeError('%s. Log output:\n%s' % (msg, log))
-
- def PullResult(self, output_path):
- if not self._device.old_interface.FileExistsOnDevice(
- self._output_file.name):
- self._FailWithLog('Perf recorded no data')
-
- perf_profile = os.path.join(output_path,
- os.path.basename(self._output_file.name))
- self._device.old_interface.PullFileFromDevice(self._output_file.name,
- perf_profile)
- if not os.stat(perf_profile).st_size:
- os.remove(perf_profile)
- self._FailWithLog('Perf recorded a zero-sized file')
-
- self._log_file.close()
- self._output_file.close()
- return perf_profile
-
-
-class PerfProfilerController(controllers.BaseController):
- def __init__(self, device, categories):
- controllers.BaseController.__init__(self)
- self._device = device
- self._categories = categories
- self._perf_binary = self._PrepareDevice(device)
- self._perf_instance = None
-
- def __repr__(self):
- return 'perf profile'
-
- @staticmethod
- def IsSupported():
- return bool(android_profiling_helper)
-
- @staticmethod
- def _PrepareDevice(device):
- if not 'BUILDTYPE' in os.environ:
- os.environ['BUILDTYPE'] = 'Release'
- return android_profiling_helper.PrepareDeviceForPerf(device)
-
- @classmethod
- def GetCategories(cls, device):
- perf_binary = cls._PrepareDevice(device)
- return device.old_interface.RunShellCommand('%s list' % perf_binary)
-
- def StartTracing(self, _):
- self._perf_instance = _PerfProfiler(self._device,
- self._perf_binary,
- self._categories)
-
- def StopTracing(self):
- if not self._perf_instance:
- return
- self._perf_instance.SignalAndWait()
-
- @staticmethod
- def _GetInteractivePerfCommand(perfhost_path, perf_profile, symfs_dir,
- required_libs, kallsyms):
- cmd = '%s report -n -i %s --symfs %s --kallsyms %s' % (
- os.path.relpath(perfhost_path, '.'), perf_profile, symfs_dir, kallsyms)
- for lib in required_libs:
- lib = os.path.join(symfs_dir, lib[1:])
- if not os.path.exists(lib):
- continue
- objdump_path = android_profiling_helper.GetToolchainBinaryPath(
- lib, 'objdump')
- if objdump_path:
- cmd += ' --objdump %s' % os.path.relpath(objdump_path, '.')
- break
- return cmd
-
- 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 = os.path.abspath(support_binaries.FindPath(
- 'perfhost', '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(constants.DIR_SOURCE_ROOT,
- 'tools', 'telemetry', 'telemetry', 'core', 'platform', 'profiler',
- 'perf_vis', '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]
- subprocess.call(cmd, stdout=json_file, stderr=dev_null)
- return json_file_name
diff --git a/build/android/chrome_profiler/perf_controller_unittest.py b/build/android/chrome_profiler/perf_controller_unittest.py
deleted file mode 100644
index a621a2e..0000000
--- a/build/android/chrome_profiler/perf_controller_unittest.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2014 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 chrome_profiler import controllers_unittest
-from chrome_profiler import perf_controller
-
-
-class PerfProfilerControllerTest(controllers_unittest.BaseControllerTest):
- def testGetCategories(self):
- if not perf_controller.PerfProfilerController.IsSupported():
- return
- categories = \
- perf_controller.PerfProfilerController.GetCategories(self.device)
- assert 'cycles' in ' '.join(categories)
-
- def testTracing(self):
- if not perf_controller.PerfProfilerController.IsSupported():
- return
- categories = ['cycles']
- controller = perf_controller.PerfProfilerController(self.device,
- categories)
-
- 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)
diff --git a/build/android/chrome_profiler/profiler.py b/build/android/chrome_profiler/profiler.py
deleted file mode 100644
index 5393ed3..0000000
--- a/build/android/chrome_profiler/profiler.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2014 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
-
-from chrome_profiler import trace_packager
-from chrome_profiler import ui
-
-from pylib import constants
-
-
-def _StartTracing(controllers, interval):
- for controller in controllers:
- controller.StartTracing(interval)
-
-
-def _StopTracing(controllers):
- for controller in controllers:
- controller.StopTracing()
-
-
-def _PullTraces(controllers, output, compress, write_json):
- ui.PrintMessage('Downloading...', eol='')
- trace_files = [controller.PullTrace() for controller in controllers]
- 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 GetSupportedBrowsers():
- """Returns the package names of all supported browsers."""
- # Add aliases for backwards compatibility.
- supported_browsers = {
- 'stable': constants.PACKAGE_INFO['chrome_stable'],
- 'beta': constants.PACKAGE_INFO['chrome_beta'],
- 'dev': constants.PACKAGE_INFO['chrome_dev'],
- 'build': constants.PACKAGE_INFO['chrome'],
- }
- supported_browsers.update(constants.PACKAGE_INFO)
- unsupported_browsers = ['content_browsertests', 'gtest', 'legacy_browser']
- for browser in unsupported_browsers:
- del supported_browsers[browser]
- return supported_browsers
-
-
-def CaptureProfile(controllers, interval, output=None, compress=False,
- write_json=False):
- """Records a profiling trace saves the result to a file.
-
- Args:
- controllers: List of tracing controllers.
- 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, controllers))
- try:
- _StartTracing(controllers, interval)
- 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(controllers)
- if interval:
- ui.PrintMessage('done')
-
- return _PullTraces(controllers, output, compress, write_json)
diff --git a/build/android/chrome_profiler/profiler_unittest.py b/build/android/chrome_profiler/profiler_unittest.py
deleted file mode 100644
index dbf8f22..0000000
--- a/build/android/chrome_profiler/profiler_unittest.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2014 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 tempfile
-import unittest
-import zipfile
-
-from chrome_profiler import profiler
-from chrome_profiler import ui
-
-
-class FakeController(object):
- def __init__(self, contents='fake-contents'):
- self.contents = contents
- self.interval = None
- self.stopped = False
- self.filename = None
-
- def StartTracing(self, interval):
- self.interval = interval
-
- def StopTracing(self):
- self.stopped = True
-
- def PullTrace(self):
- with tempfile.NamedTemporaryFile(delete=False) as f:
- self.filename = f.name
- f.write(self.contents)
- return f.name
-
- def __repr__(self):
- return 'faketrace'
-
-
-class ProfilerTest(unittest.TestCase):
- def setUp(self):
- ui.EnableTestMode()
-
- def testCaptureBasicProfile(self):
- controller = FakeController()
- interval = 1.5
- result = profiler.CaptureProfile([controller], interval)
-
- try:
- self.assertEquals(controller.interval, interval)
- self.assertTrue(controller.stopped)
- self.assertTrue(os.path.exists(result))
- self.assertFalse(os.path.exists(controller.filename))
- self.assertTrue(result.endswith('.html'))
- finally:
- os.remove(result)
-
- def testCaptureJsonProfile(self):
- controller = FakeController()
- result = profiler.CaptureProfile([controller], 1, write_json=True)
-
- try:
- self.assertFalse(result.endswith('.html'))
- with open(result) as f:
- self.assertEquals(f.read(), controller.contents)
- finally:
- os.remove(result)
-
- def testCaptureMultipleProfiles(self):
- controllers = [FakeController('c1'), FakeController('c2')]
- result = profiler.CaptureProfile(controllers, 1, write_json=True)
-
- try:
- self.assertTrue(result.endswith('.zip'))
- self.assertTrue(zipfile.is_zipfile(result))
- with zipfile.ZipFile(result) as f:
- self.assertEquals(
- f.namelist(),
- [controllers[0].filename[1:], controllers[1].filename[1:]])
- finally:
- os.remove(result)
diff --git a/build/android/chrome_profiler/run_tests b/build/android/chrome_profiler/run_tests
deleted file mode 100755
index 2cdce5a..0000000
--- a/build/android/chrome_profiler/run_tests
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-cd $(dirname $0)/..
-exec python -m unittest discover chrome_profiler '*_unittest.py'
diff --git a/build/android/chrome_profiler/systrace_controller.py b/build/android/chrome_profiler/systrace_controller.py
deleted file mode 100644
index 0903101..0000000
--- a/build/android/chrome_profiler/systrace_controller.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2014 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 threading
-import zlib
-
-from chrome_profiler import controllers
-from chrome_profiler import util
-
-from pylib import cmd_helper
-
-
-_SYSTRACE_OPTIONS = [
- # Compress the trace before sending it over USB.
- '-z',
- # Use a large trace buffer to increase the polling interval.
- '-b', '16384'
-]
-
-# Interval in seconds for sampling systrace data.
-_SYSTRACE_INTERVAL = 15
-
-
-class SystraceController(controllers.BaseController):
- def __init__(self, device, categories, ring_buffer):
- controllers.BaseController.__init__(self)
- self._device = device
- self._categories = categories
- self._ring_buffer = ring_buffer
- self._done = threading.Event()
- self._thread = None
- self._trace_data = None
-
- def __repr__(self):
- return 'systrace'
-
- @staticmethod
- def GetCategories(device):
- return device.old_interface.RunShellCommand('atrace --list_categories')
-
- def StartTracing(self, _):
- self._thread = threading.Thread(target=self._CollectData)
- self._thread.start()
-
- def StopTracing(self):
- self._done.set()
-
- def PullTrace(self):
- self._thread.join()
- self._thread = None
- if self._trace_data:
- output_name = 'systrace-%s' % util.GetTraceTimestamp()
- with open(output_name, 'w') as out:
- out.write(self._trace_data)
- return output_name
-
- def _RunATraceCommand(self, command):
- # TODO(jbudorick) can this be made work with DeviceUtils?
- # We use a separate interface to adb because the one from AndroidCommands
- # isn't re-entrant.
- device_param = (['-s', self._device.old_interface.GetDevice()]
- if self._device.old_interface.GetDevice() else [])
- cmd = ['adb'] + device_param + ['shell', 'atrace', '--%s' % command] + \
- _SYSTRACE_OPTIONS + self._categories
- return cmd_helper.GetCmdOutput(cmd)
-
- def _CollectData(self):
- trace_data = []
- self._RunATraceCommand('async_start')
- try:
- while not self._done.is_set():
- self._done.wait(_SYSTRACE_INTERVAL)
- if not self._ring_buffer or self._done.is_set():
- trace_data.append(
- self._DecodeTraceData(self._RunATraceCommand('async_dump')))
- finally:
- trace_data.append(
- self._DecodeTraceData(self._RunATraceCommand('async_stop')))
- self._trace_data = ''.join([zlib.decompress(d) for d in trace_data])
-
- @staticmethod
- def _DecodeTraceData(trace_data):
- try:
- trace_start = trace_data.index('TRACE:')
- except ValueError:
- raise RuntimeError('Systrace start marker not found')
- trace_data = trace_data[trace_start + 6:]
-
- # Collapse CRLFs that are added by adb shell.
- if trace_data.startswith('\r\n'):
- trace_data = trace_data.replace('\r\n', '\n')
-
- # Skip the initial newline.
- return trace_data[1:]
diff --git a/build/android/chrome_profiler/systrace_controller_unittest.py b/build/android/chrome_profiler/systrace_controller_unittest.py
deleted file mode 100644
index 448f328..0000000
--- a/build/android/chrome_profiler/systrace_controller_unittest.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2014 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
-
-from chrome_profiler import controllers_unittest
-from chrome_profiler import systrace_controller
-
-
-class SystraceControllerTest(controllers_unittest.BaseControllerTest):
- def testGetCategories(self):
- categories = \
- systrace_controller.SystraceController.GetCategories(self.device)
- self.assertTrue(categories)
- assert 'gfx' in ' '.join(categories)
-
- def testTracing(self):
- categories = ['gfx', 'input', 'view']
- ring_buffer = False
- controller = systrace_controller.SystraceController(self.device,
- categories,
- ring_buffer)
-
- interval = 1
- try:
- controller.StartTracing(interval)
- finally:
- controller.StopTracing()
-
- result = controller.PullTrace()
- try:
- with open(result) as f:
- self.assertTrue('CPU#' in f.read())
- finally:
- os.remove(result)
diff --git a/build/android/chrome_profiler/trace_packager.py b/build/android/chrome_profiler/trace_packager.py
deleted file mode 100644
index e56a7de..0000000
--- a/build/android/chrome_profiler/trace_packager.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2014 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 gzip
-import json
-import os
-import shutil
-import sys
-import zipfile
-
-from chrome_profiler import util
-
-from pylib import constants
-
-sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT,
- 'third_party',
- 'trace-viewer'))
-# pylint: disable=F0401
-from trace_viewer.build import trace2html
-
-
-def _PackageTracesAsHtml(trace_files, html_file):
- with open(html_file, 'w') as f:
- trace2html.WriteHTMLForTracesToFile(trace_files, f)
- for trace_file in trace_files:
- os.unlink(trace_file)
-
-
-def _CompressFile(host_file, output):
- with gzip.open(output, 'wb') as out, \
- open(host_file, 'rb') as input_file:
- out.write(input_file.read())
- os.unlink(host_file)
-
-
-def _ArchiveFiles(host_files, output):
- with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as z:
- for host_file in host_files:
- z.write(host_file)
- os.unlink(host_file)
-
-
-def _MergeTracesIfNeeded(trace_files):
- if len(trace_files) <= 1:
- return trace_files
- merge_candidates = []
- for trace_file in trace_files:
- with open(trace_file) as f:
- # Try to detect a JSON file cheaply since that's all we can merge.
- if f.read(1) != '{':
- continue
- f.seek(0)
- try:
- json_data = json.load(f)
- except ValueError:
- continue
- merge_candidates.append((trace_file, json_data))
- if len(merge_candidates) <= 1:
- return trace_files
-
- other_files = [f for f in trace_files
- if not f in [c[0] for c in merge_candidates]]
- merged_file, merged_data = merge_candidates[0]
- for trace_file, json_data in merge_candidates[1:]:
- for key, value in json_data.items():
- if not merged_data.get(key) or json_data[key]:
- merged_data[key] = value
- os.unlink(trace_file)
-
- with open(merged_file, 'w') as f:
- json.dump(merged_data, f)
- return [merged_file] + other_files
-
-
-def PackageTraces(trace_files, output=None, compress=False, write_json=False):
- trace_files = _MergeTracesIfNeeded(trace_files)
- if not write_json:
- html_file = os.path.splitext(trace_files[0])[0] + '.html'
- _PackageTracesAsHtml(trace_files, html_file)
- trace_files = [html_file]
-
- if compress and len(trace_files) == 1:
- result = output or trace_files[0] + '.gz'
- _CompressFile(trace_files[0], result)
- elif len(trace_files) > 1:
- result = output or 'chrome-combined-trace-%s.zip' % util.GetTraceTimestamp()
- _ArchiveFiles(trace_files, result)
- elif output:
- result = output
- shutil.move(trace_files[0], result)
- else:
- result = trace_files[0]
- return result
diff --git a/build/android/chrome_profiler/trace_packager_unittest.py b/build/android/chrome_profiler/trace_packager_unittest.py
deleted file mode 100644
index 8c50d3a..0000000
--- a/build/android/chrome_profiler/trace_packager_unittest.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2014 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.
-
-from chrome_profiler import trace_packager
-
-import json
-import tempfile
-import unittest
-
-
-class TracePackagerTest(unittest.TestCase):
- def testJsonTraceMerging(self):
- t1 = {'traceEvents': [{'ts': 123, 'ph': 'b'}]}
- t2 = {'traceEvents': [], 'stackFrames': ['blah']}
-
- # Both trace files will be merged to a third file and will get deleted in
- # the process, so there's no need for NamedTemporaryFile to do the
- # deletion.
- with tempfile.NamedTemporaryFile(delete=False) as f1, \
- tempfile.NamedTemporaryFile(delete=False) as f2:
- f1.write(json.dumps(t1))
- f2.write(json.dumps(t2))
- f1.flush()
- f2.flush()
-
- with tempfile.NamedTemporaryFile() as output:
- trace_packager.PackageTraces([f1.name, f2.name],
- output.name,
- compress=False,
- write_json=True)
- with open(output.name) as output:
- output = json.load(output)
- self.assertEquals(output['traceEvents'], t1['traceEvents'])
- self.assertEquals(output['stackFrames'], t2['stackFrames'])
diff --git a/build/android/chrome_profiler/ui.py b/build/android/chrome_profiler/ui.py
deleted file mode 100644
index 9913a43..0000000
--- a/build/android/chrome_profiler/ui.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2014 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 select
-import sys
-
-
-def PrintMessage(heading, eol='\n'):
- sys.stdout.write('%s%s' % (heading, eol))
- sys.stdout.flush()
-
-
-def WaitForEnter(timeout):
- select.select([sys.stdin], [], [], timeout)
-
-
-def EnableTestMode():
- def NoOp(*_, **__):
- pass
- # pylint: disable=W0601
- global PrintMessage
- global WaitForEnter
- PrintMessage = NoOp
- WaitForEnter = NoOp
diff --git a/build/android/chrome_profiler/util.py b/build/android/chrome_profiler/util.py
deleted file mode 100644
index 75ef1b6..0000000
--- a/build/android/chrome_profiler/util.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2014 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 time
-
-def GetTraceTimestamp():
- return time.strftime('%Y-%m-%d-%H%M%S', time.localtime())