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

Side by Side Diff: build/android/pylib/perf/perf_control.py

Issue 338233003: Telemetry: Set scaling governor on all cpus (on all devices) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback. 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
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging 5 import logging
6 import time 6 import time
7 7
8 from pylib import android_commands 8 from pylib import android_commands
9 from pylib.device import device_utils 9 from pylib.device import device_utils
10 10
11 11
12 class PerfControl(object): 12 class PerfControl(object):
13 """Provides methods for setting the performance mode of a device.""" 13 """Provides methods for setting the performance mode of a device."""
14 _SCALING_GOVERNOR_FMT = ( 14 _SCALING_GOVERNOR_FMT = (
15 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor') 15 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor')
16 _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online'
16 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' 17 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
17 18
18 def __init__(self, device): 19 def __init__(self, device):
19 # TODO(jbudorick) Remove once telemetry gets switched over. 20 # TODO(jbudorick) Remove once telemetry gets switched over.
20 if isinstance(device, android_commands.AndroidCommands): 21 if isinstance(device, android_commands.AndroidCommands):
21 device = device_utils.DeviceUtils(device) 22 device = device_utils.DeviceUtils(device)
22 self._device = device 23 self._device = device
23 kernel_max = self._device.old_interface.GetFileContents( 24 kernel_max = self._device.old_interface.GetFileContents(
24 PerfControl._KERNEL_MAX, log_result=False) 25 PerfControl._KERNEL_MAX, log_result=False)
25 assert kernel_max, 'Unable to find %s' % PerfControl._KERNEL_MAX 26 assert kernel_max, 'Unable to find %s' % PerfControl._KERNEL_MAX
26 self._kernel_max = int(kernel_max[0]) 27 self._kernel_max = int(kernel_max[0])
27 logging.info('Maximum CPU index: %d', self._kernel_max) 28 logging.info('Maximum CPU index: %d', self._kernel_max)
28 self._original_scaling_governor = \ 29 self._have_mpdecision = self._device.old_interface.FileExistsOnDevice(
29 self._device.old_interface.GetFileContents( 30 '/system/bin/mpdecision')
30 PerfControl._SCALING_GOVERNOR_FMT % 0, 31
31 log_result=False)[0] 32 def NumCpuCores(self):
Sami 2014/06/19 18:12:42 nit: This could be a @property (and perhaps privat
epenner 2014/06/19 23:58:50 Done.
33 return self._kernel_max + 1
34
35 def CpuOnlineFormat(self):
36 return self._CPU_ONLINE_FMT
Sami 2014/06/19 18:12:43 These two functions are only used in test code. I
epenner 2014/06/19 23:58:50 Yeah this was just for the test since accessing pr
pasko 2014/06/20 13:48:36 One other option: CpuOnlineFormatForTesting()
37
38 def ScalingGovernorFormat(self):
39 return self._SCALING_GOVERNOR_FMT
32 40
33 def SetHighPerfMode(self): 41 def SetHighPerfMode(self):
42 # TODO(epenner): Enable on all devices and remove ForceHighPerfMode
43 # http://crbug.com/383566
44 if 'Nexus 4' == self._device.old_interface.GetProductModel():
45 self._ForceAllCpusOnline(True)
46 self._SetScalingGovernorInternal('performance')
47
48 def ForceHighPerfMode(self):
pasko 2014/06/19 17:48:31 I think SetProfilingMode() would be more readable
epenner 2014/06/19 23:58:49 Changed to SetPerfProfilingMode.
34 """Sets the highest possible performance mode for the device.""" 49 """Sets the highest possible performance mode for the device."""
50 self._ForceAllCpusOnline(True)
35 self._SetScalingGovernorInternal('performance') 51 self._SetScalingGovernorInternal('performance')
36 52
37 def SetDefaultPerfMode(self): 53 def SetDefaultPerfMode(self):
38 """Sets the performance mode for the device to its default mode.""" 54 """Sets the performance mode for the device to its default mode."""
39 product_model = self._device.old_interface.GetProductModel() 55 product_model = self._device.old_interface.GetProductModel()
40 governor_mode = { 56 governor_mode = {
41 'GT-I9300': 'pegasusq', 57 'GT-I9300': 'pegasusq',
42 'Galaxy Nexus': 'interactive', 58 'Galaxy Nexus': 'interactive',
43 'Nexus 4': 'ondemand', 59 'Nexus 4': 'ondemand',
44 'Nexus 7': 'interactive', 60 'Nexus 7': 'interactive',
45 'Nexus 10': 'interactive' 61 'Nexus 10': 'interactive'
46 }.get(product_model, 'ondemand') 62 }.get(product_model, 'ondemand')
47 self._SetScalingGovernorInternal(governor_mode) 63 self._SetScalingGovernorInternal(governor_mode)
48 64 self._ForceAllCpusOnline(False)
49 def RestoreOriginalPerfMode(self):
50 """Resets the original performance mode of the device."""
51 self._SetScalingGovernorInternal(self._original_scaling_governor)
52 65
53 def _SetScalingGovernorInternal(self, value): 66 def _SetScalingGovernorInternal(self, value):
54 for cpu in range(self._kernel_max + 1): 67 for cpu in range(self.NumCpuCores()):
55 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu 68 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu
56 if self._device.old_interface.FileExistsOnDevice(scaling_governor_file): 69 if self._device.old_interface.FileExistsOnDevice(scaling_governor_file):
57 logging.info('Writing scaling governor mode \'%s\' -> %s', 70 logging.info('Writing scaling governor mode \'%s\' -> %s',
58 value, scaling_governor_file) 71 value, scaling_governor_file)
59 self._device.old_interface.SetProtectedFileContents( 72 self._device.old_interface.SetProtectedFileContents(
60 scaling_governor_file, value) 73 scaling_governor_file, value)
61 74
62 def ForceAllCpusOnline(self, force_online): 75 def _AllCpusAreOnline(self):
63 """Force all CPUs on a device to be online. 76 for cpu in range(self.NumCpuCores()):
77 online_path = PerfControl._CPU_ONLINE_FMT % cpu
78 if self._device.old_interface.GetFileContents(online_path)[0] == '0':
79 return False
80 return True
64 81
65 Force every CPU core on an Android device to remain online, or return the 82 def _ForceAllCpusOnline(self, force_online):
66 cores under system power management control. This is needed to work around 83 """Enable all CPUs on a device.
67 a bug in perf which makes it unable to record samples from CPUs that become
68 online when recording is already underway.
69 84
70 Args: 85 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise
71 force_online: True to set all CPUs online, False to return them under 86 to measurements:
72 system power management control. 87 - In perf, samples are only taken for the CPUs that are online when the
88 measurement is started.
89 - The scaling governor can't be set for an offline CPU and frequency scaling
90 on newly enabled CPUs adds noise to both perf and tracing measurements.
91
92 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm
93 this is done by "mpdecision".
94
73 """ 95 """
74 def ForceCpuOnline(online_path): 96 if self._have_mpdecision:
75 script = 'chmod 644 {0}; echo 1 > {0}; chmod 444 {0}'.format(online_path) 97 script = 'stop mpdecision' if force_online else 'start mpdecision'
76 self._device.RunShellCommand(script, root=True) 98 self._device.RunShellCommand(script, root=True)
77 return self._device.old_interface.GetFileContents(online_path)[0] == '1'
78 99
79 def ResetCpu(online_path): 100 if not self._have_mpdecision and not self._AllCpusAreOnline():
80 self._device.RunShellCommand('chmod 644 %s' % online_path, root=True) 101 logging.warn('Unexpected cpu hot plugging detected.')
pasko 2014/06/19 17:48:31 loggin.warn is deprecated, please use logging.warn
epenner 2014/06/19 23:58:50 Done.
81 102
82 def WaitFor(condition): 103 if not force_online:
83 for _ in range(100): 104 return
84 if condition():
85 return
86 time.sleep(0.1)
87 raise RuntimeError('Timed out')
88 105
89 cpu_online_files = self._device.RunShellCommand( 106 for cpu in range(self.NumCpuCores()):
90 'ls -d /sys/devices/system/cpu/cpu[0-9]*/online') 107 online_path = PerfControl._CPU_ONLINE_FMT % cpu
91 for online_path in cpu_online_files: 108 self._device.old_interface.SetProtectedFileContents(
92 if force_online: 109 online_path, "1")
Sami 2014/06/19 18:12:42 nit: '1' instead of "1"
epenner 2014/06/19 23:58:49 Done.
93 WaitFor(lambda: ForceCpuOnline(online_path)) 110
94 else: 111 # Double check all cores stayed online.
95 ResetCpu(online_path) 112 time.sleep(0.25)
113 if not self._AllCpusAreOnline():
114 raise RuntimeError('Failed to force CPUs online')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698