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

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

Issue 1332603002: [Android] Move perf utilities into devil. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: redirections for v8 Created 5 years, 3 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 2015 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 # pylint: disable=unused-wildcard-import
6 import logging 6 # pylint: disable=wildcard-import
7 7
8 from devil.android import device_errors 8 from devil.android.perf.perf_control import *
9
10
11 class PerfControl(object):
12 """Provides methods for setting the performance mode of a device."""
13 _CPU_PATH = '/sys/devices/system/cpu'
14 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
15
16 def __init__(self, device):
17 self._device = device
18 # this will raise an AdbCommandFailedError if no CPU files are found
19 self._cpu_files = self._device.RunShellCommand(
20 'ls -d cpu[0-9]*', cwd=self._CPU_PATH, check_return=True, as_root=True)
21 assert self._cpu_files, 'Failed to detect CPUs.'
22 self._cpu_file_list = ' '.join(self._cpu_files)
23 logging.info('CPUs found: %s', self._cpu_file_list)
24 self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision')
25
26 def SetHighPerfMode(self):
27 """Sets the highest stable performance mode for the device."""
28 try:
29 self._device.EnableRoot()
30 except device_errors.CommandFailedError:
31 message = 'Need root for performance mode. Results may be NOISY!!'
32 logging.warning(message)
33 # Add an additional warning at exit, such that it's clear that any results
34 # may be different/noisy (due to the lack of intended performance mode).
35 atexit.register(logging.warning, message)
36 return
37
38 product_model = self._device.product_model
39 # TODO(epenner): Enable on all devices (http://crbug.com/383566)
40 if 'Nexus 4' == product_model:
41 self._ForceAllCpusOnline(True)
42 if not self._AllCpusAreOnline():
43 logging.warning('Failed to force CPUs online. Results may be NOISY!')
44 self._SetScalingGovernorInternal('performance')
45 elif 'Nexus 5' == product_model:
46 self._ForceAllCpusOnline(True)
47 if not self._AllCpusAreOnline():
48 logging.warning('Failed to force CPUs online. Results may be NOISY!')
49 self._SetScalingGovernorInternal('performance')
50 self._SetScalingMaxFreq(1190400)
51 self._SetMaxGpuClock(200000000)
52 else:
53 self._SetScalingGovernorInternal('performance')
54
55 def SetPerfProfilingMode(self):
56 """Enables all cores for reliable perf profiling."""
57 self._ForceAllCpusOnline(True)
58 self._SetScalingGovernorInternal('performance')
59 if not self._AllCpusAreOnline():
60 if not self._device.HasRoot():
61 raise RuntimeError('Need root to force CPUs online.')
62 raise RuntimeError('Failed to force CPUs online.')
63
64 def SetDefaultPerfMode(self):
65 """Sets the performance mode for the device to its default mode."""
66 if not self._device.HasRoot():
67 return
68 product_model = self._device.product_model
69 if 'Nexus 5' == product_model:
70 if self._AllCpusAreOnline():
71 self._SetScalingMaxFreq(2265600)
72 self._SetMaxGpuClock(450000000)
73
74 governor_mode = {
75 'GT-I9300': 'pegasusq',
76 'Galaxy Nexus': 'interactive',
77 'Nexus 4': 'ondemand',
78 'Nexus 5': 'ondemand',
79 'Nexus 7': 'interactive',
80 'Nexus 10': 'interactive'
81 }.get(product_model, 'ondemand')
82 self._SetScalingGovernorInternal(governor_mode)
83 self._ForceAllCpusOnline(False)
84
85 def GetCpuInfo(self):
86 online = (output.rstrip() == '1' and status == 0
87 for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
88 governor = (output.rstrip() if status == 0 else None
89 for (_, output, status)
90 in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
91 return zip(self._cpu_files, online, governor)
92
93 def _ForEachCpu(self, cmd):
94 script = '; '.join([
95 'for CPU in %s' % self._cpu_file_list,
96 'do %s' % cmd,
97 'echo -n "%~%$?%~%"',
98 'done'
99 ])
100 output = self._device.RunShellCommand(
101 script, cwd=self._CPU_PATH, check_return=True, as_root=True)
102 output = '\n'.join(output).split('%~%')
103 return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
104
105 def _WriteEachCpuFile(self, path, value):
106 results = self._ForEachCpu(
107 'test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"'.format(
108 path=path, value=value))
109 cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
110 if cpus:
111 logging.info('Successfully set %s to %r on: %s', path, value, cpus)
112 else:
113 logging.warning('Failed to set %s to %r on any cpus', path, value)
114
115 def _SetScalingGovernorInternal(self, value):
116 self._WriteEachCpuFile('cpufreq/scaling_governor', value)
117
118 def _SetScalingMaxFreq(self, value):
119 self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
120
121 def _SetMaxGpuClock(self, value):
122 self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
123 str(value),
124 as_root=True)
125
126 def _AllCpusAreOnline(self):
127 results = self._ForEachCpu('cat "$CPU/online"')
128 # TODO(epenner): Investigate why file may be missing
129 # (http://crbug.com/397118)
130 return all(output.rstrip() == '1' and status == 0
131 for (cpu, output, status) in results
132 if cpu != 'cpu0')
133
134 def _ForceAllCpusOnline(self, force_online):
135 """Enable all CPUs on a device.
136
137 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise
138 to measurements:
139 - In perf, samples are only taken for the CPUs that are online when the
140 measurement is started.
141 - The scaling governor can't be set for an offline CPU and frequency scaling
142 on newly enabled CPUs adds noise to both perf and tracing measurements.
143
144 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm
145 this is done by "mpdecision".
146
147 """
148 if self._have_mpdecision:
149 script = 'stop mpdecision' if force_online else 'start mpdecision'
150 self._device.RunShellCommand(script, check_return=True, as_root=True)
151
152 if not self._have_mpdecision and not self._AllCpusAreOnline():
153 logging.warning('Unexpected cpu hot plugging detected.')
154
155 if force_online:
156 self._ForEachCpu('echo 1 > "$CPU/online"')
OLDNEW
« no previous file with comments | « build/android/pylib/perf/cache_control.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