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

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

Issue 73173005: Telemetry: manage CPU core online state for some device types (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 e289991f84abd918780ce520db4467e3ceb5ec64..53fb1bc7f64276bbfa3c497960be3499c91f8dd3 100644
--- a/build/android/pylib/perf/perf_control.py
+++ b/build/android/pylib/perf/perf_control.py
@@ -4,13 +4,21 @@
import logging
+import time
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')
+
_KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
+ _CPU_DIR_FMT = '/sys/devices/system/cpu/cpu%d/'
+ _SCALING_GOVERNOR_FMT = _CPU_DIR_FMT + 'cpufreq/scaling_governor'
+ _CPU_ONLINE_FMT = _CPU_DIR_FMT + 'online'
+ _SCALING_FREQUENCY_STAT_NAMES = [
+ 'cpufreq/scaling_min_freq',
+ 'cpufreq/scaling_max_freq',
+ 'cpufreq/scaling_cur_freq',
+ ]
def __init__(self, adb):
self._adb = adb
@@ -22,31 +30,126 @@ class PerfControl(object):
self._original_scaling_governor = self._adb.GetFileContents(
PerfControl._SCALING_GOVERNOR_FMT % 0,
log_result=False)[0]
+ self._LogCurrentCpuFrequencyInfo()
+
+ # Bring CPUs online/offline manually on some device types to reduce variance
+ # in performance measurements. Other device types are either hard to manage
+ # properly or we did not decide what settings look 'typical' for them.
+ # 'Galaxy Nexus' and 'Nexus 10' seem to use both cores all time without
+ # hotplugging them manually, but we still may need to manage their frequency
+ # later. TODO(pasko): manage Nexus 7 CPUs with PerfControl, v1 and v2 differ
+ # significantly.
+ #
+ # *Not managing* CPUs manually means that only a subset of CPU properties
+ # are updated (scaling governor only now) and only for those CPUs
+ # represented by sysfs at the moment (/sys/devices/system/cpu/cpuX/...)
+ self._manage_cpus_manually = False
+ cpu_indexes_to_manage_manually = {
+ 'Nexus 4': [0, 1],
+ 'Nexus 5': [0, 1],
+ }
+ device_model = self._adb.GetProductModel()
+ if device_model in cpu_indexes_to_manage_manually:
+ self._manage_cpus_manually = True
+ self._cpus_to_manage = cpu_indexes_to_manage_manually[device_model]
+ self._cpus_on_originally = []
+ for cpu in xrange(self._kernel_max + 1):
+ if '1' in self._ReadProtectedFile(PerfControl._CPU_ONLINE_FMT % cpu):
+ self._cpus_on_originally.append(cpu)
+
+ def _BringCpuOffline(self, cpu_index):
+ logging.info('Bringing CPU #%d offline.', cpu_index)
+ self._adb.SetProtectedFileContents(
+ PerfControl._CPU_ONLINE_FMT % cpu_index, '0')
+
+ def _BringCpuOnline(self, cpu_index):
+ "Brings a CPU core online, waits for it to show up in sysfs."
+
+ logging.info('Bringing CPU #%d online.' %cpu_index)
+ times_to_wait_left = 5
+ cpu_online_file = PerfControl._CPU_ONLINE_FMT % cpu_index
+ while (True):
+ self._adb.SetProtectedFileContents(cpu_online_file, '1')
+ if '1' in self._ReadProtectedFile(cpu_online_file):
+ break
+ if times_to_wait_left == 0:
+ logging.warning('Gave up bringing CPU %d online', cpu_index)
+ break
+ times_to_wait_left -= 1
+ logging.warning('Could not bring CPU %d online, retrying..',
+ cpu_index)
+ time.sleep(0.1)
+
+ def _ReadProtectedFile(self, file_name):
+ return '\n'.join(self._adb.GetProtectedFileContents(file_name))
+
+ def _LogCurrentCpuFrequencyInfo(self):
+ for cpu in xrange(self._kernel_max + 1):
+ for stat_name in PerfControl._SCALING_FREQUENCY_STAT_NAMES:
+ stat_file_name = (PerfControl._CPU_DIR_FMT + stat_name) % cpu;
+ if self._adb.FileExistsOnDevice(stat_file_name):
+ info = self._ReadProtectedFile(stat_file_name)
+ logging.info('CPU #%d frequency info: %s: %s', cpu, stat_name, info)
def SetHighPerfMode(self):
"""Sets the highest possible performance mode for the device."""
- self._SetScalingGovernorInternal('performance')
+
+ if not self._manage_cpus_manually:
+ for cpu in xrange(self._kernel_max + 1):
+ self._SetScalingGovernorInternal(cpu, 'performance')
+ else:
+ # Stop the 'mpdecision' hotplug manager to get a constant number of CPUs
+ # online when running tests. TODO(pasko): stop 'thermald'.
bulach 2013/11/19 15:13:57 make sure you send a heads up to chrome-perf-sheri
pasko 2013/11/19 18:00:08 Yes, I am planning to let sheriffs know, this can
+ self._adb.RunShellCommandWithSU('stop mpdecision')
+ for cpu in xrange(self._kernel_max + 1):
+ if cpu in self._cpus_to_manage:
+ self._BringCpuOnline(cpu)
+ self._SetScalingGovernorInternal(cpu, 'performance')
+ else:
+ self._BringCpuOffline(cpu)
def SetDefaultPerfMode(self):
"""Sets the performance mode for the device to its default mode."""
+
+ self._LogCurrentCpuFrequencyInfo()
product_model = self._adb.GetProductModel()
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._SetScalingGovernorInternal(governor_mode)
+ if not self._manage_cpus_manually:
+ # Set the default perf mode only if no CPUs were forced online.
+ for cpu in xrange(self._kernel_max + 1):
+ self._SetScalingGovernorInternal(cpu, governor_mode)
+ # If 'mpdecision' is present on the system, it will manage CPU
+ # online/offline state, otherwise it is a no-op.
+ self._adb.RunShellCommandWithSU('start mpdecision')
def RestoreOriginalPerfMode(self):
"""Resets the original performance mode of the device."""
- self._SetScalingGovernorInternal(self._original_scaling_governor)
-
- def _SetScalingGovernorInternal(self, value):
- for cpu in range(self._kernel_max + 1):
- scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu
- if self._adb.FileExistsOnDevice(scaling_governor_file):
- logging.info('Writing scaling governor mode \'%s\' -> %s',
- value, scaling_governor_file)
- self._adb.SetProtectedFileContents(scaling_governor_file, value)
+
+ self._LogCurrentCpuFrequencyInfo()
+ if not self._manage_cpus_manually:
+ for cpu in xrange(self._kernel_max + 1):
+ self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
+ else:
+ for cpu in xrange(self._kernel_max + 1):
+ if cpu in self._cpus_on_originally:
+ self._BringCpuOnline(cpu)
+ self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
+ else:
+ self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
+ self._BringCpuOffline(cpu)
+ self._adb.RunShellCommandWithSU('start mpdecision')
+
+ def _SetScalingGovernorInternal(self, cpu, value):
+ scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu
+ if (self._manage_cpus_manually or
+ self._adb.FileExistsOnDevice(scaling_governor_file)):
+ logging.info('Writing scaling governor mode "%s" -> %s',
+ value, scaling_governor_file)
+ self._adb.SetProtectedFileContents(scaling_governor_file, value)
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698