1b9485026a
resolves: rhbz#1028119 - improved tuned responsiveness resolves: rhbz#1028122
140 lines
6.1 KiB
Diff
140 lines
6.1 KiB
Diff
diff --git a/man/tuned-main.conf.5 b/man/tuned-main.conf.5
|
|
index 61a6a4b..6f324be 100644
|
|
--- a/man/tuned-main.conf.5
|
|
+++ b/man/tuned-main.conf.5
|
|
@@ -16,17 +16,31 @@ will be used. Please note if it is enabled here, it is still possible
|
|
to individually disable it in plugins.
|
|
|
|
.TP
|
|
+.BI sleep_interval= INT
|
|
+Tuned daemon is periodically waken after \fIINT\fR seconds and checks
|
|
+for events. By default this is set to 1 second. If you have Python 2
|
|
+interpreter with applied patch from Red Hat Bugzilla #917709 this
|
|
+controls responsiveness time of Tuned to commands (i.e. if you
|
|
+request profile switch, it may take up to 1 second until Tuned reacts).
|
|
+Increase this number for higher responsiveness times and more power
|
|
+savings (due to lower number of wakeups). In case you have unpatched
|
|
+Python 2 interpreter, this settings will have no visible effect,
|
|
+because the intepreter will poll 20 times per second.
|
|
+
|
|
+.TP
|
|
.BI update_interval= INT
|
|
Update interval for dynamic tuning (in seconds). Tuned daemon is periodically
|
|
waken after \fIINT\fR seconds, updates its monitors, calculates new tuning
|
|
parameters for enabled plugins and applies the changes. Plugins that have
|
|
disabled dynamic tuning are not processed. By default the \fIINT\fR is set
|
|
to 10 seconds. Tuned daemon doesn't periodically wake if dynamic tuning is
|
|
-globally disabled (see \fBdynamic_tuning\fR).
|
|
+globally disabled (see \fBdynamic_tuning\fR) or this setting set to 0.
|
|
+This must be multiple of \fBsleep_interval\fR.
|
|
|
|
.SH EXAMPLE
|
|
.nf
|
|
dynamic_tuning = 1
|
|
+sleep_interval = 1
|
|
update_interval = 10
|
|
.fi
|
|
|
|
diff --git a/tuned/consts.py b/tuned/consts.py
|
|
index 1dd53ab..6c8dc4b 100644
|
|
--- a/tuned/consts.py
|
|
+++ b/tuned/consts.py
|
|
@@ -18,5 +18,7 @@ SYSTEM_RELEASE_FILE = "/etc/system-release-cpe"
|
|
|
|
# default configuration
|
|
CFG_DEF_DYNAMIC_TUNING = True
|
|
+# how long to sleep before checking for events (in seconds)
|
|
+CFG_DEF_SLEEP_INTERVAL = 1
|
|
# update interval for dynamic tuning (in seconds)
|
|
CFG_DEF_UPDATE_INTERVAL = 10
|
|
diff --git a/tuned/daemon/application.py b/tuned/daemon/application.py
|
|
index f1b5208..e4c9da3 100644
|
|
--- a/tuned/daemon/application.py
|
|
+++ b/tuned/daemon/application.py
|
|
@@ -16,6 +16,7 @@ log = tuned.logs.get()
|
|
__all__ = ["Application"]
|
|
|
|
global_config_spec = ["dynamic_tuning = boolean(default=%s)" % consts.CFG_DEF_DYNAMIC_TUNING,
|
|
+ "sleep_interval = integer(default=%s)" % consts.CFG_DEF_SLEEP_INTERVAL,
|
|
"update_interval = integer(default=%s)" % consts.CFG_DEF_UPDATE_INTERVAL]
|
|
|
|
class Application(object):
|
|
@@ -31,7 +32,6 @@ class Application(object):
|
|
self.config = self._load_global_config()
|
|
if self.config.get("dynamic_tuning"):
|
|
log.info("dynamic tuning is enabled (can be overriden in plugins)")
|
|
- log.info("update interval is %d seconds" % self.config.get("update_interval"))
|
|
else:
|
|
log.info("dynamic tuning is globally disabled")
|
|
|
|
@@ -44,7 +44,7 @@ class Application(object):
|
|
profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger)
|
|
|
|
|
|
- self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, int(self.config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL)))
|
|
+ self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config)
|
|
self._controller = controller.Controller(self._daemon)
|
|
|
|
self._dbus_exporter = None
|
|
diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py
|
|
index 804ac0b..35f60c2 100644
|
|
--- a/tuned/daemon/daemon.py
|
|
+++ b/tuned/daemon/daemon.py
|
|
@@ -9,9 +9,27 @@ log = tuned.logs.get()
|
|
|
|
|
|
class Daemon(object):
|
|
- def __init__(self, unit_manager, profile_loader, profile_name=None, update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)):
|
|
+ def __init__(self, unit_manager, profile_loader, profile_name=None, config=None):
|
|
log.debug("initializing daemon")
|
|
- self._update_interval = update_interval
|
|
+ self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
|
|
+ self._update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)
|
|
+ self._dynamic_tuning = consts.CFG_DEF_DYNAMIC_TUNING
|
|
+ if config is not None:
|
|
+ self._sleep_interval = int(config.get("sleep_interval", consts.CFG_DEF_SLEEP_INTERVAL))
|
|
+ self._update_interval = int(config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL))
|
|
+ self._dynamic_tuning = config.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING)
|
|
+ if self._sleep_interval <= 0:
|
|
+ self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
|
|
+ if self._update_interval == 0:
|
|
+ self._dynamic_tuning = False
|
|
+ elif self._update_interval < self._sleep_interval:
|
|
+ self._update_interval = self._sleep_interval
|
|
+ self._sleep_cycles = self._update_interval // self._sleep_interval
|
|
+ log.info("using sleep interval of %d second(s)" % self._sleep_interval)
|
|
+ if self._dynamic_tuning:
|
|
+ log.info("dynamic tuning is enabled (can be overriden by plugins)")
|
|
+ log.info("using update interval of %d second(s) (%d times of the sleep interval)" % (self._sleep_cycles * self._sleep_interval, self._sleep_cycles))
|
|
+
|
|
self._unit_manager = unit_manager
|
|
self._profile_loader = profile_loader
|
|
self._init_threads()
|
|
@@ -65,11 +83,21 @@ class Daemon(object):
|
|
self._save_active_profile(self._profile.name)
|
|
self._unit_manager.start_tuning()
|
|
|
|
- while not tuned.utils.commands.wait(self._terminate, self._update_interval):
|
|
- log.debug("updating monitors")
|
|
- self._unit_manager.update_monitors()
|
|
- log.debug("performing tunings")
|
|
- self._unit_manager.update_tuning()
|
|
+ # In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
|
|
+ # poll, otherwise the python will not have chance to update events / locks (due to GIL)
|
|
+ # and e.g. DBus control will not work. The polling interval of 1 seconds (which is
|
|
+ # the default) is still much better than 50 ms polling with unpatched interpreter.
|
|
+ # For more details see tuned rhbz#917587.
|
|
+ _sleep_cnt = self._sleep_cycles
|
|
+ while not tuned.utils.commands.wait(self._terminate, self._sleep_interval):
|
|
+ if self._dynamic_tuning:
|
|
+ _sleep_cnt -= 1
|
|
+ if _sleep_cnt <= 0:
|
|
+ _sleep_cnt = self._sleep_cycles
|
|
+ log.debug("updating monitors")
|
|
+ self._unit_manager.update_monitors()
|
|
+ log.debug("performing tunings")
|
|
+ self._unit_manager.update_tuning()
|
|
|
|
self._unit_manager.stop_tuning()
|
|
self._unit_manager.destroy_all()
|