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

Side by Side 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: rebased on top of r263055 Created 6 years, 8 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 5
6 import logging 6 import logging
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 import time
9 10
10 11
11 class PerfControl(object): 12 class PerfControl(object):
12 """Provides methods for setting the performance mode of a device.""" 13 """Provides methods for setting the performance mode of a device."""
13 _SCALING_GOVERNOR_FMT = ( 14
14 '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor')
15 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' 15 _KERNEL_MAX = '/sys/devices/system/cpu/kernel_max'
16 _CPU_DIR_FMT = '/sys/devices/system/cpu/cpu%d/'
17 _SCALING_GOVERNOR_FMT = _CPU_DIR_FMT + 'cpufreq/scaling_governor'
18 _CPU_ONLINE_FMT = _CPU_DIR_FMT + 'online'
19 _SCALING_FREQUENCY_STAT_NAMES = [
20 'cpufreq/scaling_min_freq',
21 'cpufreq/scaling_max_freq',
22 'cpufreq/scaling_cur_freq',
23 ]
24 _MODELS_TO_FULLY_MANAGED_CPU_INDEXES = {
25 'Nexus 4': [0, 1, 2, 3],
26 }
16 27
17 def __init__(self, device): 28 def __init__(self, device):
18 # TODO(jbudorick) Remove once telemetry gets switched over. 29 # TODO(jbudorick) Remove once telemetry gets switched over.
19 if isinstance(device, android_commands.AndroidCommands): 30 if isinstance(device, android_commands.AndroidCommands):
20 device = device_utils.DeviceUtils(device) 31 device = device_utils.DeviceUtils(device)
21 self._device = device 32 self._device = device
22 kernel_max = self._device.old_interface.GetFileContents( 33 kernel_max = self._device.old_interface.GetFileContents(
23 PerfControl._KERNEL_MAX, log_result=False) 34 PerfControl._KERNEL_MAX, log_result=False)
24 assert kernel_max, 'Unable to find %s' % PerfControl._KERNEL_MAX 35 assert kernel_max, 'Unable to find %s' % PerfControl._KERNEL_MAX
25 self._kernel_max = int(kernel_max[0]) 36 self._kernel_max = int(kernel_max[0])
26 logging.info('Maximum CPU index: %d', self._kernel_max) 37 logging.info('Maximum CPU index: %d', self._kernel_max)
27 self._original_scaling_governor = \ 38 self._original_scaling_governor = \
28 self._device.old_interface.GetFileContents( 39 self._device.old_interface.GetFileContents(
29 PerfControl._SCALING_GOVERNOR_FMT % 0, 40 PerfControl._SCALING_GOVERNOR_FMT % 0,
30 log_result=False)[0] 41 log_result=False)[0]
42 self._LogCurrentCpuFrequencyInfo()
43
44 # Bring CPUs online/offline on some device types to reduce variance in
45 # performance measurements. Other device types are either hard to fully
46 # manage properly or we did not decide what settings look 'typical' for
47 # them. 'Galaxy Nexus' and 'Nexus 10' seem to use both cores all time
48 # without hotplugging them with PerfControl, but we still may need to manage
49 # their frequency later. TODO(pasko): manage Nexus 7 CPUs with PerfControl,
50 # v1 and v2 differ significantly.
51 #
52 # *Not fully managing* CPUs means that only a subset of CPU properties
53 # are updated (scaling governor only now) and only for those CPUs
54 # represented by sysfs at the moment (/sys/devices/system/cpu/cpuX/...)
55 self._fully_managed_cpus = (
56 self._MODELS_TO_FULLY_MANAGED_CPU_INDEXES.get(
57 self._device.old_interface.GetProductModel(), []))
58 if self._fully_managed_cpus:
59 self._cpus_on_originally = []
60 for cpu in xrange(self._kernel_max + 1):
61 if '1' in self._GetFileContents(
62 PerfControl._CPU_ONLINE_FMT % cpu):
63 self._cpus_on_originally.append(cpu)
64
65 def _BringCpuOffline(self, cpu_index):
66 logging.info('Bringing CPU #%d offline.', cpu_index)
67 self._device.old_interface.SetFileContents(
68 PerfControl._CPU_ONLINE_FMT % cpu_index, '0')
69
70 def _BringCpuOnline(self, cpu_index):
71 "Brings a CPU core online, waits for it to show up in sysfs."
72
73 logging.info('Bringing CPU #%d online.' %cpu_index)
74 times_to_wait_left = 5
75 cpu_online_file = PerfControl._CPU_ONLINE_FMT % cpu_index
76 while (True):
77 self._device.old_interface.SetFileContents(cpu_online_file, '1')
78 if '1' in self._GetFileContents(cpu_online_file):
79 break
80 if times_to_wait_left == 0:
81 logging.warning('Gave up bringing CPU %d online', cpu_index)
82 break
83 times_to_wait_left -= 1
84 logging.warning('Could not bring CPU %d online, retrying..',
85 cpu_index)
86 time.sleep(0.1)
87
88 def _GetFileContents(self, file_name):
89 return '\n'.join(self._device.old_interface.GetFileContents(file_name))
90
91 def _LogCurrentCpuFrequencyInfo(self):
92 for cpu in xrange(self._kernel_max + 1):
93 for stat_name in PerfControl._SCALING_FREQUENCY_STAT_NAMES:
94 stat_file_name = (PerfControl._CPU_DIR_FMT + stat_name) % cpu
95 if self._device.old_interface.FileExistsOnDevice(stat_file_name):
96 info = self._GetFileContents(stat_file_name)
97 logging.info('CPU #%d frequency info: %s: %s', cpu, stat_name, info)
31 98
32 def SetHighPerfMode(self): 99 def SetHighPerfMode(self):
33 """Sets the highest possible performance mode for the device.""" 100 """Sets the highest possible performance mode for the device."""
34 self._SetScalingGovernorInternal('performance') 101
102 if not self._fully_managed_cpus:
103 for cpu in xrange(self._kernel_max + 1):
104 self._SetScalingGovernorInternal(cpu, 'performance')
105 else:
106 # Stop the 'mpdecision' hotplug manager to get a constant number of CPUs
107 # online when running tests. TODO(pasko): stop 'thermald'.
108 self._device.old_interface.RunShellCommand('stop mpdecision')
109 for cpu in xrange(self._kernel_max + 1):
110 if cpu in self._fully_managed_cpus:
111 self._BringCpuOnline(cpu)
112 self._SetScalingGovernorInternal(cpu, 'performance')
113 else:
114 self._BringCpuOffline(cpu)
35 115
36 def SetDefaultPerfMode(self): 116 def SetDefaultPerfMode(self):
37 """Sets the performance mode for the device to its default mode.""" 117 """Sets the performance mode for the device to its default mode."""
118 self._LogCurrentCpuFrequencyInfo()
38 product_model = self._device.old_interface.GetProductModel() 119 product_model = self._device.old_interface.GetProductModel()
39 governor_mode = { 120 governor_mode = {
40 'GT-I9300': 'pegasusq', 121 'GT-I9300': 'pegasusq',
41 'Galaxy Nexus': 'interactive', 122 'Galaxy Nexus': 'interactive',
42 'Nexus 4': 'ondemand', 123 'Nexus 4': 'ondemand',
124 'Nexus 5': 'ondemand',
43 'Nexus 7': 'interactive', 125 'Nexus 7': 'interactive',
44 'Nexus 10': 'interactive' 126 'Nexus 10': 'interactive'
45 }.get(product_model, 'ondemand') 127 }.get(product_model, 'ondemand')
46 self._SetScalingGovernorInternal(governor_mode) 128 if not self._fully_managed_cpus:
129 # Set the default perf mode only if no CPUs were forced online.
130 for cpu in xrange(self._kernel_max + 1):
131 self._SetScalingGovernorInternal(cpu, governor_mode)
132 # If 'mpdecision' is present on the system, it will manage CPU
133 # online/offline state, otherwise it is a no-op.
134 self._device.old_interface.RunShellCommand('start mpdecision')
47 135
48 def RestoreOriginalPerfMode(self): 136 def RestoreOriginalPerfMode(self):
49 """Resets the original performance mode of the device.""" 137 """Resets the original performance mode of the device."""
50 self._SetScalingGovernorInternal(self._original_scaling_governor) 138 self._LogCurrentCpuFrequencyInfo()
139 if not self._fully_managed_cpus:
140 for cpu in xrange(self._kernel_max + 1):
141 self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
142 else:
143 for cpu in xrange(self._kernel_max + 1):
144 if cpu in self._cpus_on_originally:
145 self._BringCpuOnline(cpu)
146 self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
147 else:
148 self._SetScalingGovernorInternal(cpu, self._original_scaling_governor)
149 self._BringCpuOffline(cpu)
150 self._device.old_interface.RunShellCommand('start mpdecision')
51 151
52 def _SetScalingGovernorInternal(self, value): 152 def _SetScalingGovernorInternal(self, cpu, value):
53 for cpu in range(self._kernel_max + 1): 153 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu
54 scaling_governor_file = PerfControl._SCALING_GOVERNOR_FMT % cpu 154 if (self._fully_managed_cpus or
55 if self._device.old_interface.FileExistsOnDevice(scaling_governor_file): 155 self._device.old_interface.FileExistsOnDevice(scaling_governor_file)):
56 logging.info('Writing scaling governor mode \'%s\' -> %s', 156 logging.info('Writing scaling governor mode "%s" -> %s',
57 value, scaling_governor_file) 157 value, scaling_governor_file)
58 self._device.old_interface.SetProtectedFileContents( 158 self._device.old_interface.SetFileContents(scaling_governor_file, value)
59 scaling_governor_file, value)
60
OLDNEW
« 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