Blame SOURCES/tuned-2.3.0-timing-improvements.patch

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