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

Unified Diff: tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py

Issue 316143002: telemetry: Improve perf profiler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Poll quicker. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
diff --git a/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
index 4e0c9eae9f6bebe0731fb161f257c813be7b0921..f32eba30f7bd91b53618d5530afe6910b6b90786 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
@@ -10,9 +10,52 @@ import subprocess
import sys
import tempfile
+from telemetry.core import platform
from telemetry.core import util
from telemetry.core.platform import profiler
from telemetry.core.platform.profiler import android_profiling_helper
+from telemetry.util import support_binaries
+
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib.perf import perf_control # pylint: disable=F0401
+
+
+_PERF_OPTIONS = [
+ # In perf 3.13 --call-graph requires an argument, so use the -g short-hand
+ # which does not.
+ '-g',
+ # Increase sampling frequency for better coverage.
+ '--freq', '2000',
+]
+
+_PERF_OPTIONS_ANDROID = [
+ # Increase priority to avoid dropping samples. Requires root.
+ '--realtime', '80',
+]
+
+
+def _NicePath(path):
+ rel_path = os.path.relpath(path, os.curdir)
+ return rel_path if len(rel_path) < len(path) else path
+
+
+def _PrepareHostForPerf():
+ kptr_file = '/proc/sys/kernel/kptr_restrict'
+ with open(kptr_file) as f:
+ if f.read().strip() != '0':
+ logging.warning('Making kernel symbols unrestricted. You might have to '
+ 'enter your password for "sudo".')
+ with tempfile.NamedTemporaryFile() as zero:
+ zero.write('0')
+ zero.flush()
+ subprocess.call(['sudo', 'cp', zero.name, kptr_file])
+
+
+def _InstallPerfHost():
+ host = platform.GetHostPlatform()
+ if not host.CanLaunchApplication('perfhost'):
+ host.InstallApplication('perfhost')
+ return support_binaries.FindPath('perfhost', host.GetOSName())
class _SingleProcessPerfProfiler(object):
@@ -22,17 +65,20 @@ class _SingleProcessPerfProfiler(object):
See more details in prebuilt/android/README.txt.
"""
def __init__(self, pid, output_file, browser_backend, platform_backend,
- perf_binary):
+ perf_binary, perfhost_binary):
self._pid = pid
self._browser_backend = browser_backend
self._platform_backend = platform_backend
self._output_file = output_file
self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
self._is_android = platform_backend.GetOSName() == 'android'
+ self._perfhost_binary = perfhost_binary
cmd_prefix = []
+ perf_args = ['record', '--pid', str(pid)]
if self._is_android:
cmd_prefix = ['adb', '-s', browser_backend.adb.device_serial(), 'shell',
perf_binary]
+ perf_args += _PERF_OPTIONS_ANDROID
output_file = os.path.join('/sdcard', 'perf_profiles',
os.path.basename(output_file))
self._device_output_file = output_file
@@ -41,11 +87,8 @@ class _SingleProcessPerfProfiler(object):
browser_backend.adb.RunShellCommand('rm -f ' + self._device_output_file)
else:
cmd_prefix = [perf_binary]
- # In perf 3.13 --call-graph requires an argument, so use
- # the -g short-hand which does not.
- self._proc = subprocess.Popen(cmd_prefix +
- ['record', '-g',
- '--pid', str(pid), '--output', output_file],
+ perf_args += ['--output', output_file] + _PERF_OPTIONS
+ self._proc = subprocess.Popen(cmd_prefix + perf_args,
stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
def CollectProfile(self):
@@ -77,7 +120,8 @@ Try rerunning this script under sudo or setting
self._GetStdOut()))
finally:
self._tmp_output_file.close()
- cmd = 'perf report -n -i %s' % self._output_file
+ cmd = '%s report -n -i %s' % (_NicePath(self._perfhost_binary),
+ self._output_file)
if self._is_android:
device = self._browser_backend.adb.device()
device.old_interface.Adb().Pull(self._device_output_file,
@@ -91,13 +135,15 @@ Try rerunning this script under sudo or setting
required_libs,
use_symlinks=True)
cmd += ' --symfs %s --kallsyms %s' % (symfs_root, kallsyms)
-
- objdump_path = os.path.join(os.environ.get('ANDROID_TOOLCHAIN',
- '$ANDROID_TOOLCHAIN'),
- 'arm-linux-androideabi-objdump')
- print 'If you have recent version of perf (3.10+), append the following '
- print 'to see annotated source code (by pressing the \'a\' key): '
- print ' --objdump %s' % objdump_path
+ for lib in required_libs:
+ lib = os.path.join(symfs_root, lib[1:])
+ if not os.path.exists(lib):
+ continue
+ objdump_path = android_profiling_helper.GetToolchainBinaryPath(
+ lib, 'objdump')
+ if objdump_path:
+ cmd += ' --objdump %s' % _NicePath(objdump_path)
+ break
print 'To view the profile, run:'
print ' ', cmd
@@ -119,17 +165,29 @@ class PerfProfiler(profiler.Profiler):
browser_backend, platform_backend, output_path, state)
process_output_file_map = self._GetProcessOutputFileMap()
self._process_profilers = []
- perf_binary = 'perf'
- if platform_backend.GetOSName() == 'android':
- perf_binary = android_profiling_helper.PrepareDeviceForPerf(
- browser_backend.adb.device())
+ self._is_android = platform_backend.GetOSName() == 'android'
- for pid, output_file in process_output_file_map.iteritems():
- if 'zygote' in output_file:
- continue
- self._process_profilers.append(
- _SingleProcessPerfProfiler(
- pid, output_file, browser_backend, platform_backend, perf_binary))
+ perf_binary = perfhost_binary = _InstallPerfHost()
+ try:
+ if self._is_android:
+ device = browser_backend.adb.device()
+ perf_binary = android_profiling_helper.PrepareDeviceForPerf(device)
+ self._perf_control = perf_control.PerfControl(device)
+ self._perf_control.ForceAllCpusOnline(True)
+ else:
+ _PrepareHostForPerf()
+
+ for pid, output_file in process_output_file_map.iteritems():
+ if 'zygote' in output_file:
+ continue
+ self._process_profilers.append(
+ _SingleProcessPerfProfiler(
+ pid, output_file, browser_backend, platform_backend,
+ perf_binary, perfhost_binary))
+ except:
+ if self._is_android:
+ self._perf_control.ForceAllCpusOnline(False)
+ raise
@classmethod
def name(cls):
@@ -141,17 +199,7 @@ class PerfProfiler(profiler.Profiler):
return False
if browser_type.startswith('cros'):
return False
- return cls._CheckLinuxPerf() or browser_type.startswith('android')
-
- @classmethod
- def _CheckLinuxPerf(cls):
- try:
- with open(os.devnull, 'w') as devnull:
- return not subprocess.Popen(['perf', '--version'],
- stderr=devnull,
- stdout=devnull).wait()
- except OSError:
- return False
+ return True
@classmethod
def CustomizeBrowserOptions(cls, browser_type, options):
@@ -161,6 +209,8 @@ class PerfProfiler(profiler.Profiler):
])
def CollectProfile(self):
+ if self._is_android:
+ self._perf_control.ForceAllCpusOnline(False)
output_files = []
for single_process in self._process_profilers:
output_files.append(single_process.CollectProfile())
@@ -173,8 +223,9 @@ class PerfProfiler(profiler.Profiler):
"""
assert os.path.exists(file_name)
with open(os.devnull, 'w') as devnull:
+ _InstallPerfHost()
report = subprocess.Popen(
- ['perf', 'report', '--show-total-period', '-U', '-t', '^', '-i',
+ ['perfhost', 'report', '--show-total-period', '-U', '-t', '^', '-i',
file_name],
stdout=subprocess.PIPE, stderr=devnull).communicate()[0]
period_by_function = {}
« no previous file with comments | « tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698