fixed race condition in the start/stop code

resolves: rhbz#1028119
- improved tuned responsiveness
  resolves: rhbz#1028122
This commit is contained in:
Jaroslav Škarvada 2013-11-13 23:17:59 +01:00
parent 31203de546
commit 1b9485026a
3 changed files with 170 additions and 1 deletions

View File

@ -0,0 +1,20 @@
diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py
index 9741cac..804ac0b 100644
--- a/tuned/daemon/daemon.py
+++ b/tuned/daemon/daemon.py
@@ -65,7 +65,6 @@ class Daemon(object):
self._save_active_profile(self._profile.name)
self._unit_manager.start_tuning()
- self._terminate.clear()
while not tuned.utils.commands.wait(self._terminate, self._update_interval):
log.debug("updating monitors")
self._unit_manager.update_monitors()
@@ -105,6 +104,7 @@ class Daemon(object):
log.info("starting tuning")
self._thread = threading.Thread(target=self._thread_code)
+ self._terminate.clear()
self._thread.start()
return True

View File

@ -0,0 +1,139 @@
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()

View File

@ -1,7 +1,7 @@
Summary: A dynamic adaptive system tuning daemon
Name: tuned
Version: 2.3.0
Release: 1%{?dist}
Release: 2%{?dist}
License: GPLv2+
Source: https://fedorahosted.org/releases/t/u/tuned/tuned-%{version}.tar.bz2
URL: https://fedorahosted.org/tuned/
@ -12,6 +12,8 @@ Requires(preun): systemd
Requires(postun): systemd
Requires: python-decorator, dbus-python, pygobject3-base, python-pyudev
Requires: virt-what, python-configobj, ethtool, gawk
Patch0: tuned-2.3.0-fix-race.patch
Patch1: tuned-2.3.0-timing-improvements.patch
%description
The tuned package contains a daemon that tunes system settings dynamically.
@ -51,6 +53,8 @@ It can be also used to fine tune your system for specific scenarios.
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%build
@ -155,6 +159,12 @@ sed -i 's|.*/\([^/]\+\)/[^\.]\+\.conf|\1|' /etc/tuned/active_profile
%{_prefix}/lib/tuned/spindown-disk
%changelog
* Fri Nov 8 2013 Jaroslav Škarvada <jskarvad@redhat.com> - 2.3.0-2
- fixed race condition in the start/stop code
resolves: rhbz#1028119
- improved tuned responsiveness
resolves: rhbz#1028122
* Wed Nov 6 2013 Jaroslav Škarvada <jskarvad@redhat.com> - 2.3.0-1
- new-release
resolves: rhbz#1020743