1 # Copyright (c) 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.
10 from telemetry.core import exceptions
11 from telemetry.core import util
12 from telemetry.core.platform import profiler
15 class _SingleProcessSampleProfiler(object):
16 """An internal class for using iprofiler for a given process."""
17 def __init__(self, pid, output_path):
18 self._output_path = output_path
19 self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
20 self._proc = subprocess.Popen(
21 ['sample', str(pid), '-mayDie', '-file', self._output_path],
22 stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
24 stdout = self._GetStdOut()
25 if 'sample cannot examine process' in stdout:
26 raise exceptions.ProfilingException(
27 'Failed to start sample for process %s\n' %
28 self._output_path.split('.')[1])
29 return 'Sampling process' in stdout
30 util.WaitFor(IsStarted, 120)
32 def CollectProfile(self):
33 self._proc.send_signal(signal.SIGINT)
34 exit_code = self._proc.wait()
38 'sample failed with exit code %d. Output:\n%s' % (
39 exit_code, self._GetStdOut()))
42 self._tmp_output_file.close()
44 print 'To view the profile, run:'
45 print ' open -a TextEdit %s' % self._output_path
47 return self._output_path
50 self._tmp_output_file.flush()
52 with open(self._tmp_output_file.name) as f:
58 class SampleProfiler(profiler.Profiler):
60 def __init__(self, browser_backend, platform_backend, output_path, state):
61 super(SampleProfiler, self).__init__(
62 browser_backend, platform_backend, output_path, state)
63 process_output_file_map = self._GetProcessOutputFileMap()
64 self._process_profilers = []
65 for pid, output_file in process_output_file_map.iteritems():
66 if '.utility' in output_file:
67 # The utility process may not have been started by Telemetry.
68 # So we won't have permissing to profile it
70 self._process_profilers.append(
71 _SingleProcessSampleProfiler(pid, output_file))
78 def is_supported(cls, browser_type):
79 if sys.platform != 'darwin':
81 if browser_type == 'any':
83 return (not browser_type.startswith('android') and
84 not browser_type.startswith('cros'))
86 def CollectProfile(self):
88 for single_process in self._process_profilers:
89 output_paths.append(single_process.CollectProfile())