diff options
Diffstat (limited to 'tools/telemetry')
3 files changed, 128 insertions, 1 deletions
diff --git a/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py new file mode 100644 index 0000000..66ea97e --- /dev/null +++ b/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py @@ -0,0 +1,65 @@ +# Copyright (c) 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 os +import signal +import sys + +from telemetry.core import util +from telemetry.core.platform import profiler + +# pexpect is not available on all platforms so use the third_party version. +sys.path.append(os.path.join( + os.path.abspath(os.path.dirname(__file__)), '..', '..', '..', '..', '..', + '..', 'third_party', 'pexpect')) +import pexpect # pylint: disable=F0401 + + +class IprofilerProfiler(profiler.Profiler): + + def __init__(self, browser_backend, pid, output_path): + super(IprofilerProfiler, self).__init__(output_path) + self._browser_backend = browser_backend + output_dir = os.path.dirname(self.output_path) + output_file = os.path.basename(self.output_path) + self._proc = pexpect.spawn( + 'iprofiler', ['-timeprofiler', '-T', '300', '-a', str(pid), + '-d', output_dir, '-o', output_file], + timeout=300) + while True: + if self._proc.getecho(): + output = self._proc.readline().strip() + if not output: + continue + if 'iprofiler: Profiling process' in output: + break + print output + self._proc.interact(escape_character='\x0d') + self._proc.write('\x0d') + print + def Echo(): + return self._proc.getecho() + util.WaitFor(Echo, timeout=5) + + @classmethod + def name(cls): + return 'iprofiler' + + @classmethod + def is_supported(cls, options): + return (sys.platform == 'darwin' + and not options.browser_type.startswith('android') + and not options.browser_type.startswith('cros')) + + def CollectProfile(self): + self._proc.kill(signal.SIGINT) + try: + self._proc.wait() + except pexpect.ExceptionPexpect: + pass + finally: + self._proc = None + + print 'To view the profile, run:' + print ' open -a Instruments %s.dtps' % self.output_path diff --git a/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py b/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py index cb81cbc..9ae2510 100644 --- a/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py +++ b/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py @@ -2,10 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from telemetry.core.platform.profiler import iprofiler_profiler from telemetry.core.platform.profiler import perf_profiler +from telemetry.core.platform.profiler import sample_profiler -_PROFILERS = [perf_profiler.PerfProfiler] +_PROFILERS = [iprofiler_profiler.IprofilerProfiler, + perf_profiler.PerfProfiler, + sample_profiler.SampleProfiler] def FindProfiler(name): diff --git a/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py new file mode 100644 index 0000000..608b59d --- /dev/null +++ b/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py @@ -0,0 +1,58 @@ +# Copyright (c) 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 signal +import subprocess +import sys +import tempfile + +from telemetry.core import util +from telemetry.core.platform import profiler + + +class SampleProfiler(profiler.Profiler): + + def __init__(self, browser_backend, pid, output_path): + super(SampleProfiler, self).__init__(output_path) + self._browser_backend = browser_backend + self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0) + self._proc = subprocess.Popen( + ['sample', str(pid), '-mayDie', '-file', self.output_path], + stdout=self._tmp_output_file, stderr=subprocess.STDOUT) + def IsStarted(): + return 'Sampling process' in self._GetStdOut() + util.WaitFor(IsStarted, 120) + + @classmethod + def name(cls): + return 'sample' + + @classmethod + def is_supported(cls, options): + return (sys.platform == 'darwin' + and not options.browser_type.startswith('android') + and not options.browser_type.startswith('cros')) + + def CollectProfile(self): + self._proc.send_signal(signal.SIGINT) + exit_code = self._proc.wait() + try: + if exit_code: + raise Exception( + 'sample failed with exit code %d. Output:\n%s' % ( + exit_code, self._GetStdOut())) + finally: + self._proc = None + self._tmp_output_file.close() + + print 'To view the profile, run:' + print ' open -a TextEdit %s' % self.output_path + + def _GetStdOut(self): + self._tmp_output_file.flush() + try: + with open(self._tmp_output_file.name) as f: + return f.read() + except IOError: + return '' |