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.
10 from telemetry
.core
import exceptions
11 from telemetry
.internal
.platform
import profiler
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
)
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()
39 'sample failed with exit code %d. Output:\n%s' % (
40 exit_code
, self
._GetStdOut
()))
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
51 self
._tmp
_output
_file
.flush()
53 with
open(self
._tmp
_output
_file
.name
) as f
:
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
71 self
._process
_profilers
.append(
72 _SingleProcessSampleProfiler(pid
, output_file
))
79 def is_supported(cls
, browser_type
):
80 if sys
.platform
!= 'darwin':
82 if browser_type
== 'any':
84 return (not browser_type
.startswith('android') and
85 not browser_type
.startswith('cros'))
87 def CollectProfile(self
):
89 for single_process
in self
._process
_profilers
:
90 output_paths
.append(single_process
.CollectProfile())