Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: build/android/chrome_profiler/perf_controller.py

Issue 293193002: adb_profile_chrome: Add perf profiler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unneeded entrypoint. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright 2014 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.
4
5 import logging
6 import os
7 import subprocess
8 import sys
9 import tempfile
10
11 from chrome_profiler import controllers
12
13 from pylib import android_commands
14 from pylib import constants
15
16 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT,
17 'tools',
18 'telemetry'))
19 try:
20 # pylint: disable=F0401
21 from telemetry.core.platform.profiler import android_profiling_helper
22 from telemetry.util import support_binaries
23 except ImportError:
24 android_profiling_helper = None
25 support_binaries = None
26
27
28 _PERF_OPTIONS = [
29 # Sample across all processes and CPUs to so that the current CPU gets
30 # recorded to each sample.
31 '--all-cpus',
32 # In perf 3.13 --call-graph requires an argument, so use the -g short-hand
33 # which does not.
34 '-g',
35 # Increase priority to avoid dropping samples. Requires root.
36 '--realtime', '80',
37 # Record raw samples to get CPU information.
38 '--raw-samples',
39 # Increase sampling frequency for better coverage.
40 '--freq', '2000',
41 ]
42
43
44 class _PerfProfiler(object):
45 def __init__(self, device, perf_binary, categories):
46 self._device = device
47 self._output_file = android_commands.DeviceTempFile(
48 self._device.old_interface, prefix='perf_output')
49 self._log_file = tempfile.TemporaryFile()
50
51 device_param = (['-s', self._device.old_interface.GetDevice()]
52 if self._device.old_interface.GetDevice() else [])
53 cmd = ['adb'] + device_param + \
54 ['shell', perf_binary, 'record',
55 '--output', self._output_file.name] + _PERF_OPTIONS
56 if categories:
57 cmd += ['--event', ','.join(categories)]
58 self._perf_process = subprocess.Popen(cmd,
59 stdout=self._log_file,
60 stderr=subprocess.STDOUT)
61
62 def SignalAndWait(self):
63 perf_pids = self._device.old_interface.ExtractPid('perf')
64 self._device.old_interface.RunShellCommand(
65 'kill -SIGINT ' + ' '.join(perf_pids))
66 self._perf_process.wait()
67
68 def _FailWithLog(self, msg):
69 self._log_file.seek(0)
70 log = self._log_file.read()
71 raise RuntimeError('%s. Log output:\n%s' % (msg, log))
72
73 def PullResult(self, output_path):
74 if not self._device.old_interface.FileExistsOnDevice(
75 self._output_file.name):
76 self._FailWithLog('Perf recorded no data')
77
78 perf_profile = os.path.join(output_path,
79 os.path.basename(self._output_file.name))
80 self._device.old_interface.PullFileFromDevice(self._output_file.name,
81 perf_profile)
82 if not os.stat(perf_profile).st_size:
83 os.remove(perf_profile)
84 self._FailWithLog('Perf recorded a zero-sized file')
85
86 self._log_file.close()
87 self._output_file.close()
88 return perf_profile
89
90
91 class PerfProfilerController(controllers.BaseController):
92 def __init__(self, device, categories):
93 controllers.BaseController.__init__(self)
94 self._device = device
95 self._categories = categories
96 self._perf_binary = self._PrepareDevice(device)
97 self._perf_instance = None
98
99 def __repr__(self):
100 return 'perf profile'
101
102 @staticmethod
103 def IsSupported():
104 return bool(android_profiling_helper)
105
106 @staticmethod
107 def _PrepareDevice(device):
108 if not 'BUILDTYPE' in os.environ:
109 os.environ['BUILDTYPE'] = 'Release'
110 return android_profiling_helper.PrepareDeviceForPerf(device)
111
112 @classmethod
113 def GetCategories(cls, device):
114 perf_binary = cls._PrepareDevice(device)
115 return device.old_interface.RunShellCommand('%s list' % perf_binary)
116
117 def StartTracing(self, _):
118 self._perf_instance = _PerfProfiler(self._device,
119 self._perf_binary,
120 self._categories)
121
122 def StopTracing(self):
123 if not self._perf_instance:
124 return
125 self._perf_instance.SignalAndWait()
126
127 def PullTrace(self):
128 symfs_dir = os.path.join(tempfile.gettempdir(),
129 os.path.expandvars('$USER-perf-symfs'))
130 if not os.path.exists(symfs_dir):
131 os.makedirs(symfs_dir)
132 required_libs = set()
133
134 # Download the recorded perf profile.
135 perf_profile = self._perf_instance.PullResult(symfs_dir)
136 required_libs = \
137 android_profiling_helper.GetRequiredLibrariesForPerfProfile(
138 perf_profile)
139 if not required_libs:
140 logging.warning('No libraries required by perf trace. Most likely there '
141 'are no samples in the trace.')
142
143 # Build a symfs with all the necessary libraries.
144 kallsyms = android_profiling_helper.CreateSymFs(self._device,
145 symfs_dir,
146 required_libs,
147 use_symlinks=False)
148 # Convert the perf profile into JSON.
149 perfhost_path = os.path.abspath(support_binaries.FindPath(
150 'perfhost', 'linux'))
151 perf_script_path = os.path.join(constants.DIR_SOURCE_ROOT,
152 'tools', 'telemetry', 'telemetry', 'core', 'platform', 'profiler',
153 'perf_vis', 'perf_to_tracing.py')
154 json_file_name = os.path.basename(perf_profile)
155 with open(os.devnull, 'w') as dev_null, \
156 open(json_file_name, 'w') as json_file:
157 cmd = [perfhost_path, 'script', '-s', perf_script_path, '-i',
158 perf_profile, '--symfs', symfs_dir, '--kallsyms', kallsyms]
159 subprocess.call(cmd, stdout=json_file, stderr=dev_null)
160 return json_file_name
OLDNEW
« no previous file with comments | « build/android/chrome_profiler/main.py ('k') | build/android/chrome_profiler/perf_controller_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698