1
0
Fork 0

plugin_cpu: added support for sampling_down_factor and removed cpupower

The sampling rate determines how frequently the governor checks to tune the
CPU. The sampling_down_factor is a tunable that multiplies the sampling rate
when the CPU is at its highest clock frequency thereby delaying load
evaluation and improving performance. Allowed values for
sampling_down_factor are 1 to 100000.

Usage:

[cpu]
sampling_down_factor = 1

Recommended setting for jitter reduction:
sampling_down_factor = 100

Original idea of adding support for this knob to Tuned came from
Akshay Adiga <akshay.adiga@linux.vnet.ibm.com>

This patch also removes cpupower support from Tuned. It seems
that cpupower tool changes it's output format time to time, and parsing
it in Tuned becomes harder and harder. Morever the current parser in Tuned
didn't handle the recent cpupower correctly. It's much easier to just query
sysfs than supporting multiple versions of cpupower.

Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
Jaroslav Škarvada 2016-06-23 11:24:41 +02:00
parent b85e9c2180
commit 6bf3afa9d3

View file

@ -22,13 +22,13 @@ class CPULatencyPlugin(base.Plugin):
super(self.__class__, self).__init__(*args, **kwargs)
self._has_pm_qos = True
self._has_cpupower = True
self._has_energy_perf_bias = True
self._has_intel_pstate = False
self._min_perf_pct_save = None
self._max_perf_pct_save = None
self._no_turbo_save = None
self._governors_map = {}
self._cmd = commands()
def _init_devices(self):
@ -43,24 +43,18 @@ class CPULatencyPlugin(base.Plugin):
@classmethod
def _get_config_options(self):
return {
"load_threshold" : 0.2,
"latency_low" : 100,
"latency_high" : 1000,
"force_latency" : None,
"governor" : None,
"energy_perf_bias" : None,
"min_perf_pct" : None,
"max_perf_pct" : None,
"no_turbo" : None,
"load_threshold" : 0.2,
"latency_low" : 100,
"latency_high" : 1000,
"force_latency" : None,
"governor" : None,
"sampling_down_factor" : None,
"energy_perf_bias" : None,
"min_perf_pct" : None,
"max_perf_pct" : None,
"no_turbo" : None,
}
def _check_cpupower(self):
if self._cmd.execute(["cpupower", "frequency-info"], no_errors = [errno.ENOENT])[0] == 0:
self._has_cpupower = True
else:
self._has_cpupower = False
log.warning("unable to run cpupower tool, using sysfs fallback, is cpupower installed?")
def _check_energy_perf_bias(self):
self._has_energy_perf_bias = False
retcode = self._cmd.execute(["x86_energy_perf_policy", "-r"], no_errors = [errno.ENOENT])[0]
@ -112,8 +106,6 @@ class CPULatencyPlugin(base.Plugin):
else:
instance._load_monitor = None
# Check for cpupower, use workaround if not available
self._check_cpupower()
# Check for x86_energy_perf_policy, ignore if not available / supported
self._check_energy_perf_bias()
# Check for intel_pstate
@ -205,11 +197,7 @@ class CPULatencyPlugin(base.Plugin):
return None
if not sim:
log.info("setting governor '%s' on cpu '%s'" % (governor, device))
if self._has_cpupower:
cpu_id = device.lstrip("cpu")
self._cmd.execute(["cpupower", "-c", cpu_id, "frequency-set", "-g", str(governor)])
else:
self._cmd.write_to_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor" % device, str(governor))
self._cmd.write_to_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor" % device, str(governor))
return str(governor)
@command_get("governor")
@ -217,28 +205,55 @@ class CPULatencyPlugin(base.Plugin):
governor = None
if not self._check_cpu_can_change_governor(device):
return None
if self._has_cpupower:
cpu_id = device.lstrip("cpu")
retcode, lines = self._cmd.execute(["cpupower", "-c", cpu_id, "frequency-info", "-p"])
if retcode == 0:
for line in lines.splitlines():
if line.startswith("analyzing"):
continue
l = line.split()
if len(l) == 3:
governor = l[2].strip()
break
else:
data = self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor" % device).strip()
if len(data) > 0:
governor = data
data = self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor" % device).strip()
if len(data) > 0:
governor = data
if governor is None:
log.error("could not get current governor on cpu '%s'" % device)
return governor
def _sampling_down_factor_path(self, governor = "ondemand"):
return "/sys/devices/system/cpu/cpufreq/%s/sampling_down_factor" % governor
@command_set("sampling_down_factor", per_device = True, priority = 10)
def _set_sampling_down_factor(self, sampling_down_factor, device, sim):
val = None
# hack to clear governors map when the profile starts unloading
# TODO: this should be handled better way, by e.g. currently non-implemented
# Plugin.profile_load_finished() method
if device in self._governors_map:
self._governors_map.clear()
self._governors_map[device] = None
governor = self._get_governor(device)
if governor is None:
log.debug("ignoring sampling_down_factor setting for CPU '%s', cannot match governor" % device)
return None
if governor not in self._governors_map.values():
self._governors_map[device] = governor
path = self._sampling_down_factor_path(governor)
if not os.path.exists(path):
log.debug("ignoring sampling_down_factor setting for CPU '%s', governor '%s' doesn't support it" % (device, governor))
return None
val = str(sampling_down_factor)
if not sim:
log.info("setting sampling_down_factor to '%s' for governor '%s'" % (val, governor))
self._cmd.write_to_file(path, val)
return val
@command_get("sampling_down_factor")
def _get_sampling_down_factor(self, device):
governor = self._get_governor(device)
if governor is None:
return None
path = self._sampling_down_factor_path(governor)
if not os.path.exists(path):
return None
return self._cmd.read_file(path).strip()
@command_set("energy_perf_bias", per_device=True)
def _set_energy_perf_bias(self, energy_perf_bias, device, sim):
if not self._is_cpu_online(device):