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

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

Issue 754433003: Update from https://crrev.com/305340 (Closed) Base URL: git@github.com:domokit/mojo.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 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 atexit 5 import atexit
6 import logging 6 import logging
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 class PerfControl(object): 11 class PerfControl(object):
12 """Provides methods for setting the performance mode of a device.""" 12 """Provides methods for setting the performance mode of a device."""
13 _SCALING_GOVERNOR_FMT = ( 13 _CPU_PATH = '/sys/devices/system/cpu'
14 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor')
15 _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online'
16 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' 14 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
17 15
18 def __init__(self, device): 16 def __init__(self, device):
19 # TODO(jbudorick) Remove once telemetry gets switched over. 17 # TODO(jbudorick) Remove once telemetry gets switched over.
20 if isinstance(device, android_commands.AndroidCommands): 18 if isinstance(device, android_commands.AndroidCommands):
21 device = device_utils.DeviceUtils(device) 19 device = device_utils.DeviceUtils(device)
22 self._device = device 20 self._device = device
23 cpu_files = self._device.RunShellCommand( 21 # this will raise an AdbShellCommandFailedError if no CPU files are found
24 'ls -d /sys/devices/system/cpu/cpu[0-9]*') 22 self._cpu_files = self._device.RunShellCommand(
25 self._num_cpu_cores = len(cpu_files) 23 'ls -d cpu[0-9]*', cwd=self._CPU_PATH, check_return=True, as_root=True)
26 assert self._num_cpu_cores > 0, 'Failed to detect CPUs.' 24 assert self._cpu_files, 'Failed to detect CPUs.'
27 logging.info('Number of CPUs: %d', self._num_cpu_cores) 25 self._cpu_file_list = ' '.join(self._cpu_files)
26 logging.info('CPUs found: %s', self._cpu_file_list)
28 self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision') 27 self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
29 28
30 def SetHighPerfMode(self): 29 def SetHighPerfMode(self):
31 """Sets the highest stable performance mode for the device.""" 30 """Sets the highest stable performance mode for the device."""
32 if not self._device.old_interface.IsRootEnabled(): 31 if not self._device.old_interface.IsRootEnabled():
33 message = 'Need root for performance mode. Results may be NOISY!!' 32 message = 'Need root for performance mode. Results may be NOISY!!'
34 logging.warning(message) 33 logging.warning(message)
35 # Add an additional warning at exit, such that it's clear that any results 34 # Add an additional warning at exit, such that it's clear that any results
36 # may be different/noisy (due to the lack of intended performance mode). 35 # may be different/noisy (due to the lack of intended performance mode).
37 atexit.register(logging.warning, message) 36 atexit.register(logging.warning, message)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 'GT-I9300': 'pegasusq', 76 'GT-I9300': 'pegasusq',
78 'Galaxy Nexus': 'interactive', 77 'Galaxy Nexus': 'interactive',
79 'Nexus 4': 'ondemand', 78 'Nexus 4': 'ondemand',
80 'Nexus 5': 'ondemand', 79 'Nexus 5': 'ondemand',
81 'Nexus 7': 'interactive', 80 'Nexus 7': 'interactive',
82 'Nexus 10': 'interactive' 81 'Nexus 10': 'interactive'
83 }.get(product_model, 'ondemand') 82 }.get(product_model, 'ondemand')
84 self._SetScalingGovernorInternal(governor_mode) 83 self._SetScalingGovernorInternal(governor_mode)
85 self._ForceAllCpusOnline(False) 84 self._ForceAllCpusOnline(False)
86 85
86 def GetCpuInfo(self):
87 online = (output.rstrip() == '1' and status == 0
88 for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
89 governor = (output.rstrip() if status == 0 else None
90 for (_, output, status)
91 in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
92 return zip(self._cpu_files, online, governor)
93
94 def _ForEachCpu(self, cmd):
95 script = '; '.join([
96 'for CPU in %s' % self._cpu_file_list,
97 'do %s' % cmd,
98 'echo -n "%~%$?%~%"',
99 'done'
100 ])
101 output = self._device.RunShellCommand(
102 script, cwd=self._CPU_PATH, check_return=True, as_root=True)
103 output = '\n'.join(output).split('%~%')
104 return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
105
106 def _WriteEachCpuFile(self, path, value):
107 results = self._ForEachCpu(
108 'test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"'.format(
109 path=path, value=value))
110 cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
111 if cpus:
112 logging.info('Successfully set %s to %r on: %s', path, value, cpus)
113 else:
114 logging.warning('Failed to set %s to %r on any cpus')
115
87 def _SetScalingGovernorInternal(self, value): 116 def _SetScalingGovernorInternal(self, value):
88 cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)]) 117 self._WriteEachCpuFile('cpufreq/scaling_governor', value)
89 script = ('for CPU in %s; do\n'
90 ' FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_governor"\n'
91 ' test -e $FILE && echo %s > $FILE\n'
92 'done\n') % (cpu_cores, value)
93 logging.info('Setting scaling governor mode: %s', value)
94 self._device.RunShellCommand(script, as_root=True)
95 118
96 def _SetScalingMaxFreq(self, value): 119 def _SetScalingMaxFreq(self, value):
97 cpu_cores = ' '.join([str(x) for x in range(self._num_cpu_cores)]) 120 self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
98 script = ('for CPU in %s; do\n'
99 ' FILE="/sys/devices/system/cpu/cpu$CPU/cpufreq/scaling_max_freq"\n'
100 ' test -e $FILE && echo %d > $FILE\n'
101 'done\n') % (cpu_cores, value)
102 self._device.RunShellCommand(script, as_root=True)
103 121
104 def _SetMaxGpuClock(self, value): 122 def _SetMaxGpuClock(self, value):
105 self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk', 123 self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
106 str(value), 124 str(value),
107 as_root=True) 125 as_root=True)
108 126
109 def _AllCpusAreOnline(self): 127 def _AllCpusAreOnline(self):
110 for cpu in range(1, self._num_cpu_cores): 128 results = self._ForEachCpu('cat "$CPU/online"')
111 online_path = PerfControl._CPU_ONLINE_FMT % cpu 129 # TODO(epenner): Investigate why file may be missing
112 # TODO(epenner): Investigate why file may be missing 130 # (http://crbug.com/397118)
113 # (http://crbug.com/397118) 131 return all(output.rstrip() == '1' and status == 0
114 if not self._device.FileExists(online_path) or \ 132 for (cpu, output, status) in results
115 self._device.ReadFile(online_path)[0] == '0': 133 if cpu != 'cpu0')
116 return False
117 return True
118 134
119 def _ForceAllCpusOnline(self, force_online): 135 def _ForceAllCpusOnline(self, force_online):
120 """Enable all CPUs on a device. 136 """Enable all CPUs on a device.
121 137
122 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise 138 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise
123 to measurements: 139 to measurements:
124 - In perf, samples are only taken for the CPUs that are online when the 140 - In perf, samples are only taken for the CPUs that are online when the
125 measurement is started. 141 measurement is started.
126 - The scaling governor can't be set for an offline CPU and frequency scaling 142 - The scaling governor can't be set for an offline CPU and frequency scaling
127 on newly enabled CPUs adds noise to both perf and tracing measurements. 143 on newly enabled CPUs adds noise to both perf and tracing measurements.
128 144
129 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm 145 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm
130 this is done by "mpdecision". 146 this is done by "mpdecision".
131 147
132 """ 148 """
133 if self._have_mpdecision: 149 if self._have_mpdecision:
134 script = 'stop mpdecision' if force_online else 'start mpdecision' 150 script = 'stop mpdecision' if force_online else 'start mpdecision'
135 self._device.RunShellCommand(script, as_root=True) 151 self._device.RunShellCommand(script, check_return=True, as_root=True)
136 152
137 if not self._have_mpdecision and not self._AllCpusAreOnline(): 153 if not self._have_mpdecision and not self._AllCpusAreOnline():
138 logging.warning('Unexpected cpu hot plugging detected.') 154 logging.warning('Unexpected cpu hot plugging detected.')
139 155
140 if not force_online: 156 if force_online:
141 return 157 self._ForEachCpu('echo 1 > "$CPU/online"')
142
143 for cpu in range(self._num_cpu_cores):
144 online_path = PerfControl._CPU_ONLINE_FMT % cpu
145 self._device.WriteFile(online_path, '1', as_root=True)
146
OLDNEW
« no previous file with comments | « build/android/pylib/linker/test_runner.py ('k') | build/android/pylib/perf/perf_control_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698