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

Unified Diff: build/android/pylib/perf/perf_control.py

Issue 732473003: A more robust way to set/query CPU properties on devices (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month 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
Index: build/android/pylib/perf/perf_control.py
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py
index ede131789d70faca081d3810e5ccafb659adfb07..6e40ef8429afc89589a6a8f64c3408709a7e3e2a 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -4,15 +4,15 @@
import atexit
import logging
+import posixpath
from pylib import android_commands
+from pylib import cmd_helper
from pylib.device import device_utils
class PerfControl(object):
"""Provides methods for setting the performance mode of a device."""
- _SCALING_GOVERNOR_FMT = (
- '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor')
- _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online'
+ _CPU_PATH = '/sys/devices/system/cpu'
_KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
def __init__(self, device):
@@ -20,11 +20,11 @@ class PerfControl(object):
if isinstance(device, android_commands.AndroidCommands):
device = device_utils.DeviceUtils(device)
self._device = device
- cpu_files = self._device.RunShellCommand(
- 'ls -d /sys/devices/system/cpu/cpu[0-9]*')
- self._num_cpu_cores = len(cpu_files)
- assert self._num_cpu_cores > 0, 'Failed to detect CPUs.'
- logging.info('Number of CPUs: %d', self._num_cpu_cores)
+ self._cpu_files = self._device.RunShellCommand(
+ 'cd %s && ls -d cpu[0-9]*' % self._CPU_PATH,
Sami 2014/11/18 13:24:04 nit: You could replace "ls -d" with "echo" here.
perezju 2014/11/18 17:42:41 "ls -d" is more robust. If for whatever reason the
+ check_return=True, as_root=True)
perezju 2014/11/17 21:20:56 This will already throw an exception if either the
+ self._cpu_file_list = ' '.join(self._cpu_files)
+ logging.info('CPUs found: %s', self._cpu_file_list)
self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
def SetHighPerfMode(self):
@@ -84,22 +84,40 @@ class PerfControl(object):
self._SetScalingGovernorInternal(governor_mode)
self._ForceAllCpusOnline(False)
+ def GetCpuInfo(self):
+ online = (out.rstrip() == '1' and code == 0
Sami 2014/11/18 13:24:04 nit: I think something like |exit_status| may be a
perezju 2014/11/18 17:42:42 Acknowledged. I went for |status| just to keep it
+ for (_, out, code) in self._ForEachCpu('cat "$CPU/online"'))
+ governor = (out.rstrip() if code == 0 else None
+ for (_, out, code) in
+ self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
+ return zip(self._cpu_files, online, governor)
+
+ def _ForEachCpu(self, cmd):
+ script = ('cd %s\n'
+ 'for CPU in %s; do\n'
+ ' %s; echo -n "%%~%%$?%%~%%"\n'
jbudorick 2014/11/18 02:29:38 What's the reasoning behind "%~%$?%~%"? Do we jus
Sami 2014/11/18 13:24:04 Alternatively we could append the exit codes to a
perezju 2014/11/18 17:42:42 The reasoning is basically just that. Also I thin
+ 'done' % (self._CPU_PATH, self._cpu_file_list, cmd))
jbudorick 2014/11/18 02:29:38 I think this would be more readable if you handled
perezju 2014/11/18 17:42:42 Acknowledged.
+ output = self._device.RunShellCommand(script, check_return=True,
+ as_root=True, raw_output=True)
jbudorick 2014/11/18 02:29:38 I don't think this justifies adding raw_output to
+ output = output.split('%~%')
+ return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
perezju 2014/11/17 21:20:56 This is where the magic happens now, for each cpu
+
+ def _WriteEachCpuFile(self, path, value):
+ cmd = ('test -e %(path)s && echo %(value)s > %(path)s' % {
+ 'path': cmd_helper.DoubleQuote(posixpath.join('$CPU', path)),
jbudorick 2014/11/18 02:29:37 posixpath.join?
perezju 2014/11/18 17:42:42 ok, ok, _maybe_ I don't have to be this much defen
+ 'value': value})
+ output = self._ForEachCpu(cmd)
+ cpus = ' '.join(cpu for (cpu, _, code) in output if code == 0)
+ if cpus:
+ logging.info('Succesfully set %s to %r on: %s', path, value, cpus)
+ else:
+ logging.warning('Failed to set %s to %r on any cpus')
+
def _SetScalingGovernorInternal(self, value):
- cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)])
- script = ('for CPU in %s; do\n'
- ' FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_governor"\n'
- ' test -e $FILE && echo %s > $FILE\n'
- 'done\n') % (cpu_cores, value)
- logging.info('Setting scaling governor mode: %s', value)
- self._device.RunShellCommand(script, as_root=True)
+ self._WriteEachCpuFile('cpufreq/scaling_governor', value)
def _SetScalingMaxFreq(self, value):
- cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)])
- script = ('for CPU in %s; do\n'
- ' FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_max_freq"\n'
- ' test -e $FILE && echo %d > $FILE\n'
- 'done\n') % (cpu_cores, value)
- self._device.RunShellCommand(script, as_root=True)
+ self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
def _SetMaxGpuClock(self, value):
self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
@@ -107,14 +125,12 @@ class PerfControl(object):
as_root=True)
def _AllCpusAreOnline(self):
- for cpu in range(1, self._num_cpu_cores):
- online_path = PerfControl._CPU_ONLINE_FMT % cpu
- # TODO(epenner): Investigate why file may be missing
- # (http://crbug.com/397118)
- if not self._device.FileExists(online_path) or \
- self._device.ReadFile(online_path)[0] == '0':
- return False
- return True
+ output = self._ForEachCpu('cat "$CPU/online"')
+ return all(out.rstrip() == '1' and code == 0
perezju 2014/11/17 21:20:56 code will be non-zero if the file does not exist,
+ for (cpu, out, code) in output
+ # TODO(epenner): Investigate why cpu0/online may be missing
+ # (http://crbug.com/397118)
+ if cpu != 'cpu0')
def _ForceAllCpusOnline(self, force_online):
"""Enable all CPUs on a device.
@@ -132,15 +148,10 @@ class PerfControl(object):
"""
if self._have_mpdecision:
script = 'stop mpdecision' if force_online else 'start mpdecision'
- self._device.RunShellCommand(script, as_root=True)
+ self._device.RunShellCommand(script, check_return=True, as_root=True)
if not self._have_mpdecision and not self._AllCpusAreOnline():
logging.warning('Unexpected cpu hot plugging detected.')
- if not force_online:
- return
-
- for cpu in range(self._num_cpu_cores):
- online_path = PerfControl._CPU_ONLINE_FMT % cpu
- self._device.WriteFile(online_path, '1', as_root=True)
-
+ if force_online:
+ self._ForEachCpu('echo 1 > "$CPU/online"')

Powered by Google App Engine
This is Rietveld 408576698