summaryrefslogtreecommitdiff
path: root/third_party/catapult/devil/devil/android/perf/perf_control.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/catapult/devil/devil/android/perf/perf_control.py')
-rw-r--r--third_party/catapult/devil/devil/android/perf/perf_control.py210
1 files changed, 0 insertions, 210 deletions
diff --git a/third_party/catapult/devil/devil/android/perf/perf_control.py b/third_party/catapult/devil/devil/android/perf/perf_control.py
deleted file mode 100644
index 06a5db61e5..0000000000
--- a/third_party/catapult/devil/devil/android/perf/perf_control.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import atexit
-import logging
-import re
-
-from devil.android import device_errors
-
-logger = logging.getLogger(__name__)
-
-
-class PerfControl(object):
- """Provides methods for setting the performance mode of a device."""
-
- _AVAILABLE_GOVERNORS_REL_PATH = 'cpufreq/scaling_available_governors'
- _CPU_FILE_PATTERN = re.compile(r'^cpu\d+$')
- _CPU_PATH = '/sys/devices/system/cpu'
- _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
-
- def __init__(self, device):
- self._device = device
- self._cpu_files = [
- filename
- for filename in self._device.ListDirectory(self._CPU_PATH, as_root=True)
- if self._CPU_FILE_PATTERN.match(filename)]
- assert self._cpu_files, 'Failed to detect CPUs.'
- self._cpu_file_list = ' '.join(self._cpu_files)
- logger.info('CPUs found: %s', self._cpu_file_list)
-
- self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
-
- raw = self._ReadEachCpuFile(self._AVAILABLE_GOVERNORS_REL_PATH)
- self._available_governors = [
- (cpu, raw_governors.strip().split() if not exit_code else None)
- for cpu, raw_governors, exit_code in raw]
-
- def SetHighPerfMode(self):
- """Sets the highest stable performance mode for the device."""
- try:
- self._device.EnableRoot()
- except device_errors.CommandFailedError:
- message = 'Need root for performance mode. Results may be NOISY!!'
- logger.warning(message)
- # Add an additional warning at exit, such that it's clear that any results
- # may be different/noisy (due to the lack of intended performance mode).
- atexit.register(logger.warning, message)
- return
-
- product_model = self._device.product_model
- # TODO(epenner): Enable on all devices (http://crbug.com/383566)
- if 'Nexus 4' == product_model:
- self._ForceAllCpusOnline(True)
- if not self._AllCpusAreOnline():
- logger.warning('Failed to force CPUs online. Results may be NOISY!')
- self.SetScalingGovernor('performance')
- elif 'Nexus 5' == product_model:
- self._ForceAllCpusOnline(True)
- if not self._AllCpusAreOnline():
- logger.warning('Failed to force CPUs online. Results may be NOISY!')
- self.SetScalingGovernor('performance')
- self._SetScalingMaxFreq(1190400)
- self._SetMaxGpuClock(200000000)
- else:
- self.SetScalingGovernor('performance')
-
- def SetPerfProfilingMode(self):
- """Enables all cores for reliable perf profiling."""
- self._ForceAllCpusOnline(True)
- self.SetScalingGovernor('performance')
- if not self._AllCpusAreOnline():
- if not self._device.HasRoot():
- raise RuntimeError('Need root to force CPUs online.')
- raise RuntimeError('Failed to force CPUs online.')
-
- def SetDefaultPerfMode(self):
- """Sets the performance mode for the device to its default mode."""
- if not self._device.HasRoot():
- return
- product_model = self._device.product_model
- if 'Nexus 5' == product_model:
- if self._AllCpusAreOnline():
- self._SetScalingMaxFreq(2265600)
- self._SetMaxGpuClock(450000000)
-
- governor_mode = {
- 'GT-I9300': 'pegasusq',
- 'Galaxy Nexus': 'interactive',
- 'Nexus 4': 'ondemand',
- 'Nexus 5': 'ondemand',
- 'Nexus 7': 'interactive',
- 'Nexus 10': 'interactive'
- }.get(product_model, 'ondemand')
- self.SetScalingGovernor(governor_mode)
- self._ForceAllCpusOnline(False)
-
- def GetCpuInfo(self):
- online = (output.rstrip() == '1' and status == 0
- for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
- governor = (output.rstrip() if status == 0 else None
- for (_, output, status)
- in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
- return zip(self._cpu_files, online, governor)
-
- def _ForEachCpu(self, cmd):
- script = '; '.join([
- 'for CPU in %s' % self._cpu_file_list,
- 'do %s' % cmd,
- 'echo -n "%~%$?%~%"',
- 'done'
- ])
- output = self._device.RunShellCommand(
- script, cwd=self._CPU_PATH, check_return=True, as_root=True, shell=True)
- output = '\n'.join(output).split('%~%')
- return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
-
- def _WriteEachCpuFile(self, path, value):
- self._ConditionallyWriteEachCpuFile(path, value, condition='true')
-
- def _ConditionallyWriteEachCpuFile(self, path, value, condition):
- template = (
- '{condition} && test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"')
- results = self._ForEachCpu(
- template.format(path=path, value=value, condition=condition))
- cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
- if cpus:
- logger.info('Successfully set %s to %r on: %s', path, value, cpus)
- else:
- logger.warning('Failed to set %s to %r on any cpus', path, value)
-
- def _ReadEachCpuFile(self, path):
- return self._ForEachCpu(
- 'cat "$CPU/{path}"'.format(path=path))
-
- def SetScalingGovernor(self, value):
- """Sets the scaling governor to the given value on all possible CPUs.
-
- This does not attempt to set a governor to a value not reported as available
- on the corresponding CPU.
-
- Args:
- value: [string] The new governor value.
- """
- condition = 'test -e "{path}" && grep -q {value} {path}'.format(
- path=('${CPU}/%s' % self._AVAILABLE_GOVERNORS_REL_PATH),
- value=value)
- self._ConditionallyWriteEachCpuFile(
- 'cpufreq/scaling_governor', value, condition)
-
- def GetScalingGovernor(self):
- """Gets the currently set governor for each CPU.
-
- Returns:
- An iterable of 2-tuples, each containing the cpu and the current
- governor.
- """
- raw = self._ReadEachCpuFile('cpufreq/scaling_governor')
- return [
- (cpu, raw_governor.strip() if not exit_code else None)
- for cpu, raw_governor, exit_code in raw]
-
- def ListAvailableGovernors(self):
- """Returns the list of available governors for each CPU.
-
- Returns:
- An iterable of 2-tuples, each containing the cpu and a list of available
- governors for that cpu.
- """
- return self._available_governors
-
- def _SetScalingMaxFreq(self, value):
- self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
-
- def _SetMaxGpuClock(self, value):
- self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
- str(value),
- as_root=True)
-
- def _AllCpusAreOnline(self):
- results = self._ForEachCpu('cat "$CPU/online"')
- # TODO(epenner): Investigate why file may be missing
- # (http://crbug.com/397118)
- return all(output.rstrip() == '1' and status == 0
- for (cpu, output, status) in results
- if cpu != 'cpu0')
-
- def _ForceAllCpusOnline(self, force_online):
- """Enable all CPUs on a device.
-
- Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise
- to measurements:
- - In perf, samples are only taken for the CPUs that are online when the
- measurement is started.
- - The scaling governor can't be set for an offline CPU and frequency scaling
- on newly enabled CPUs adds noise to both perf and tracing measurements.
-
- It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm
- this is done by "mpdecision".
-
- """
- if self._have_mpdecision:
- cmd = ['stop', 'mpdecision'] if force_online else ['start', 'mpdecision']
- self._device.RunShellCommand(cmd, check_return=True, as_root=True)
-
- if not self._have_mpdecision and not self._AllCpusAreOnline():
- logger.warning('Unexpected cpu hot plugging detected.')
-
- if force_online:
- self._ForEachCpu('echo 1 > "$CPU/online"')