Update sdk/platform-tools to version 26.0.0.
[android_tools.git] / sdk / platform-tools / systrace / catapult / telemetry / telemetry / internal / platform / profiler / sample_profiler.py
blob19559014888f7b2803d58f1d90fdafe89a7a4577
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import signal
6 import subprocess
7 import sys
8 import tempfile
10 from telemetry.core import exceptions
11 from telemetry.internal.platform import profiler
13 import py_utils
16 class _SingleProcessSampleProfiler(object):
17 """An internal class for using iprofiler for a given process."""
18 def __init__(self, pid, output_path):
19 self._output_path = output_path
20 self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
21 self._proc = subprocess.Popen(
22 ['sample', str(pid), '-mayDie', '-file', self._output_path],
23 stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
24 def IsStarted():
25 stdout = self._GetStdOut()
26 if 'sample cannot examine process' in stdout:
27 raise exceptions.ProfilingException(
28 'Failed to start sample for process %s\n' %
29 self._output_path.split('.')[1])
30 return 'Sampling process' in stdout
31 py_utils.WaitFor(IsStarted, 120)
33 def CollectProfile(self):
34 self._proc.send_signal(signal.SIGINT)
35 exit_code = self._proc.wait()
36 try:
37 if exit_code:
38 raise Exception(
39 'sample failed with exit code %d. Output:\n%s' % (
40 exit_code, self._GetStdOut()))
41 finally:
42 self._proc = None
43 self._tmp_output_file.close()
45 print 'To view the profile, run:'
46 print ' open -a TextEdit %s' % self._output_path
48 return self._output_path
50 def _GetStdOut(self):
51 self._tmp_output_file.flush()
52 try:
53 with open(self._tmp_output_file.name) as f:
54 return f.read()
55 except IOError:
56 return ''
59 class SampleProfiler(profiler.Profiler):
61 def __init__(self, browser_backend, platform_backend, output_path, state):
62 super(SampleProfiler, self).__init__(
63 browser_backend, platform_backend, output_path, state)
64 process_output_file_map = self._GetProcessOutputFileMap()
65 self._process_profilers = []
66 for pid, output_file in process_output_file_map.iteritems():
67 if '.utility' in output_file:
68 # The utility process may not have been started by Telemetry.
69 # So we won't have permissing to profile it
70 continue
71 self._process_profilers.append(
72 _SingleProcessSampleProfiler(pid, output_file))
74 @classmethod
75 def name(cls):
76 return 'sample'
78 @classmethod
79 def is_supported(cls, browser_type):
80 if sys.platform != 'darwin':
81 return False
82 if browser_type == 'any':
83 return True
84 return (not browser_type.startswith('android') and
85 not browser_type.startswith('cros'))
87 def CollectProfile(self):
88 output_paths = []
89 for single_process in self._process_profilers:
90 output_paths.append(single_process.CollectProfile())
91 return output_paths