OLD | NEW |
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 | 6 |
7 from pylib import android_commands | 7 from pylib import android_commands |
8 from pylib.device import device_utils | 8 from pylib.device import device_utils |
9 | 9 |
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 _SCALING_GOVERNOR_FMT = ( |
14 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor') | 14 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor') |
15 _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online' | 15 _CPU_ONLINE_FMT = '/sys/devices/system/cpu/cpu%d/online' |
16 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' | 16 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' |
17 | 17 |
18 def __init__(self, device): | 18 def __init__(self, device): |
19 # TODO(jbudorick) Remove once telemetry gets switched over. | 19 # TODO(jbudorick) Remove once telemetry gets switched over. |
20 if isinstance(device, android_commands.AndroidCommands): | 20 if isinstance(device, android_commands.AndroidCommands): |
21 device = device_utils.DeviceUtils(device) | 21 device = device_utils.DeviceUtils(device) |
22 self._device = device | 22 self._device = device |
23 cpu_files = self._device.RunShellCommand( | 23 cpu_files = self._device.RunShellCommand( |
24 'ls -d /sys/devices/system/cpu/cpu[0-9]*') | 24 'ls -d /sys/devices/system/cpu/cpu[0-9]*') |
25 self._num_cpu_cores = len(cpu_files) | 25 self._num_cpu_cores = len(cpu_files) |
26 assert self._num_cpu_cores > 0, 'Failed to detect CPUs.' | 26 assert self._num_cpu_cores > 0, 'Failed to detect CPUs.' |
27 logging.info('Number of CPUs: %d', self._num_cpu_cores) | 27 logging.info('Number of CPUs: %d', self._num_cpu_cores) |
28 self._have_mpdecision = self._device.old_interface.FileExistsOnDevice( | 28 self._have_mpdecision = self._device.FileExists('/system/bin/mpdecision') |
29 '/system/bin/mpdecision') | |
30 | 29 |
31 def SetHighPerfMode(self): | 30 def SetHighPerfMode(self): |
32 # TODO(epenner): Enable on all devices (http://crbug.com/383566) | 31 # TODO(epenner): Enable on all devices (http://crbug.com/383566) |
33 if 'Nexus 4' == self._device.old_interface.GetProductModel(): | 32 if 'Nexus 4' == self._device.old_interface.GetProductModel(): |
34 self._ForceAllCpusOnline(True) | 33 self._ForceAllCpusOnline(True) |
35 if not self._AllCpusAreOnline(): | 34 if not self._AllCpusAreOnline(): |
36 logging.warning('Failed to force CPUs online. Results may be noisy!') | 35 logging.warning('Failed to force CPUs online. Results may be noisy!') |
37 self._SetScalingGovernorInternal('performance') | 36 self._SetScalingGovernorInternal('performance') |
38 | 37 |
39 def SetPerfProfilingMode(self): | 38 def SetPerfProfilingMode(self): |
(...skipping 14 matching lines...) Expand all Loading... |
54 'Nexus 4': 'ondemand', | 53 'Nexus 4': 'ondemand', |
55 'Nexus 7': 'interactive', | 54 'Nexus 7': 'interactive', |
56 'Nexus 10': 'interactive' | 55 'Nexus 10': 'interactive' |
57 }.get(product_model, 'ondemand') | 56 }.get(product_model, 'ondemand') |
58 self._SetScalingGovernorInternal(governor_mode) | 57 self._SetScalingGovernorInternal(governor_mode) |
59 self._ForceAllCpusOnline(False) | 58 self._ForceAllCpusOnline(False) |
60 | 59 |
61 def _SetScalingGovernorInternal(self, value): | 60 def _SetScalingGovernorInternal(self, value): |
62 for cpu in range(self._num_cpu_cores): | 61 for cpu in range(self._num_cpu_cores): |
63 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu | 62 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu |
64 if self._device.old_interface.FileExistsOnDevice(scaling_governor_file): | 63 if self._device.FileExists(scaling_governor_file): |
65 logging.info('Writing scaling governor mode \'%s\' -> %s', | 64 logging.info('Writing scaling governor mode \'%s\' -> %s', |
66 value, scaling_governor_file) | 65 value, scaling_governor_file) |
67 self._device.old_interface.SetProtectedFileContents( | 66 self._device.WriteFile(scaling_governor_file, value, as_root=True) |
68 scaling_governor_file, value) | |
69 | 67 |
70 def _AllCpusAreOnline(self): | 68 def _AllCpusAreOnline(self): |
71 for cpu in range(self._num_cpu_cores): | 69 for cpu in range(self._num_cpu_cores): |
72 online_path = PerfControl._CPU_ONLINE_FMT % cpu | 70 online_path = PerfControl._CPU_ONLINE_FMT % cpu |
73 if self._device.old_interface.GetFileContents(online_path)[0] == '0': | 71 if self._device.ReadFile(online_path)[0] == '0': |
74 return False | 72 return False |
75 return True | 73 return True |
76 | 74 |
77 def _ForceAllCpusOnline(self, force_online): | 75 def _ForceAllCpusOnline(self, force_online): |
78 """Enable all CPUs on a device. | 76 """Enable all CPUs on a device. |
79 | 77 |
80 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise | 78 Some vendors (or only Qualcomm?) hot-plug their CPUs, which can add noise |
81 to measurements: | 79 to measurements: |
82 - In perf, samples are only taken for the CPUs that are online when the | 80 - In perf, samples are only taken for the CPUs that are online when the |
83 measurement is started. | 81 measurement is started. |
84 - The scaling governor can't be set for an offline CPU and frequency scaling | 82 - The scaling governor can't be set for an offline CPU and frequency scaling |
85 on newly enabled CPUs adds noise to both perf and tracing measurements. | 83 on newly enabled CPUs adds noise to both perf and tracing measurements. |
86 | 84 |
87 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm | 85 It appears Qualcomm is the only vendor that hot-plugs CPUs, and on Qualcomm |
88 this is done by "mpdecision". | 86 this is done by "mpdecision". |
89 | 87 |
90 """ | 88 """ |
91 if self._have_mpdecision: | 89 if self._have_mpdecision: |
92 script = 'stop mpdecision' if force_online else 'start mpdecision' | 90 script = 'stop mpdecision' if force_online else 'start mpdecision' |
93 self._device.RunShellCommand(script, as_root=True) | 91 self._device.RunShellCommand(script, as_root=True) |
94 | 92 |
95 if not self._have_mpdecision and not self._AllCpusAreOnline(): | 93 if not self._have_mpdecision and not self._AllCpusAreOnline(): |
96 logging.warning('Unexpected cpu hot plugging detected.') | 94 logging.warning('Unexpected cpu hot plugging detected.') |
97 | 95 |
98 if not force_online: | 96 if not force_online: |
99 return | 97 return |
100 | 98 |
101 for cpu in range(self._num_cpu_cores): | 99 for cpu in range(self._num_cpu_cores): |
102 online_path = PerfControl._CPU_ONLINE_FMT % cpu | 100 online_path = PerfControl._CPU_ONLINE_FMT % cpu |
103 self._device.old_interface.SetProtectedFileContents( | 101 self._device.WriteFile(online_path, '1', as_root=True) |
104 online_path, '1') | |
OLD | NEW |