1
0
Fork 0

Merge pull request #16 from olysonek/instance_priority_pr

Implement instance priority
This commit is contained in:
Jaroslav Škarvada 2017-02-17 16:45:02 +01:00 committed by GitHub
commit 9cf6c3f45c
6 changed files with 54 additions and 41 deletions

View file

@ -26,3 +26,6 @@ recommend_command = 1
# If enabled these sysctls will be re-appliead after Tuned sysctls are
# applied, i.e. Tuned sysctls will not override system sysctls.
reapply_sysctl = 1
# Default priority assigned to instances
default_instance_priority = 0

View file

@ -56,6 +56,7 @@ CFG_SLEEP_INTERVAL = "sleep_interval"
CFG_UPDATE_INTERVAL = "update_interval"
CFG_RECOMMEND_COMMAND = "recommend_command"
CFG_REAPPLY_SYSCTL = "reapply_sysctl"
CFG_DEFAULT_INSTANCE_PRIORITY = "default_instance_priority"
# no_daemon mode
CFG_DEF_DAEMON = True
@ -69,6 +70,8 @@ CFG_DEF_UPDATE_INTERVAL = 10
CFG_DEF_RECOMMEND_COMMAND = True
# reapply system sysctl
CFG_DEF_REAPPLY_SYSCTL = True
# default instance priority
CFG_DEF_DEFAULT_INSTANCE_PRIORITY = 0
PATH_CPU_DMA_LATENCY = "/dev/cpu_dma_latency"

View file

@ -34,7 +34,8 @@ class Application(object):
log.info("dynamic tuning is globally disabled")
plugins_repository = plugins.Repository(monitors_repository, storage_factory, hardware_inventory, device_matcher, plugin_instance_factory, self.config, self.variables)
unit_manager = units.Manager(plugins_repository, monitors_repository)
def_instance_priority = int(self.config.get(consts.CFG_DEFAULT_INSTANCE_PRIORITY, consts.CFG_DEF_DEFAULT_INSTANCE_PRIORITY))
unit_manager = units.Manager(plugins_repository, monitors_repository, def_instance_priority)
profile_factory = profiles.Factory()
profile_merger = profiles.Merger()

View file

@ -102,11 +102,10 @@ class Plugin(object):
self._destroy_instance(instance)
del self._instances[instance.name]
def initialize_instances(self):
"""Initialize all created instances."""
for (instance_name, instance) in self._instances.items():
log.debug("initializing instance %s (%s)" % (instance_name, self.name))
self._instance_init(instance)
def initialize_instance(self, instance):
"""Initialize an instance."""
log.debug("initializing instance %s (%s)" % (instance.name, self.name))
self._instance_init(instance)
def destroy_instances(self):
"""Destroy all instances."""
@ -140,21 +139,20 @@ class Plugin(object):
def _get_matching_devices(self, instance, devices):
return set(self._device_matcher.match_list(instance.devices_expression, devices))
def assign_free_devices(self):
def assign_free_devices(self, instance):
if not self._devices_supported():
return
log.debug("assigning devices to all instances")
for instance_name, instance in reversed(self._instances.items()):
to_assign = self._get_matching_devices(instance, self._free_devices)
instance.active = len(to_assign) > 0
if not instance.active:
log.warn("instance %s: no matching devices available" % instance_name)
else:
log.info("instance %s: assigning devices %s" % (instance_name, ", ".join(to_assign)))
instance.devices.update(to_assign) # cannot use |=
self._assigned_devices |= to_assign
self._free_devices -= to_assign
log.debug("assigning devices to instance %s" % instance.name)
to_assign = self._get_matching_devices(instance, self._free_devices)
instance.active = len(to_assign) > 0
if not instance.active:
log.warn("instance %s: no matching devices available" % instance.name)
else:
log.info("instance %s: assigning devices %s" % (instance.name, ", ".join(to_assign)))
instance.devices.update(to_assign) # cannot use |=
self._assigned_devices |= to_assign
self._free_devices -= to_assign
def release_devices(self, instance):
if not self._devices_supported():

View file

@ -15,6 +15,10 @@ class Instance(object):
# properties
@property
def plugin(self):
return self._plugin
@property
def name(self):
return self._name

View file

@ -1,3 +1,4 @@
import collections
import tuned.exceptions
import tuned.logs
import tuned.plugins.exceptions
@ -11,10 +12,11 @@ class Manager(object):
Manager creates plugin instances and keeps a track of them.
"""
def __init__(self, plugins_repository, monitors_repository):
def __init__(self, plugins_repository, monitors_repository, def_instance_priority):
super(self.__class__, self).__init__()
self._plugins_repository = plugins_repository
self._monitors_repository = monitors_repository
self._def_instance_priority = def_instance_priority
self._instances = []
self._plugins = []
@ -27,22 +29,25 @@ class Manager(object):
return self._instances
def create(self, instances_config):
# group instances by plugin
instances_by_plugin = {}
instance_info_list = []
for instance_name, instance_info in instances_config.items():
if not instance_info.enabled:
log.debug("skipping disabled instance '%s'" % instance_name)
continue
instances_by_plugin.setdefault(instance_info.type, [])
instances_by_plugin[instance_info.type].append(instance_info)
instance_info.options.setdefault("instance_priority", self._def_instance_priority)
instance_info.options["instance_priority"] = int(instance_info.options["instance_priority"])
instance_info_list.append(instance_info)
# create all plugin instances at once
instance_info_list.sort(key=lambda x: x.options["instance_priority"])
plugins_by_name = collections.OrderedDict()
for instance_info in instance_info_list:
instance_info.options.pop("instance_priority")
plugins_by_name[instance_info.type] = None
for plugin_name, instances_info in instances_by_plugin.items():
for plugin_name, none in plugins_by_name.items():
try:
plugin = self._plugins_repository.create(plugin_name)
plugins_by_name[plugin_name] = plugin
self._plugins.append(plugin)
except tuned.plugins.exceptions.NotSupportedPluginException:
log.info("skipping plugin '%s', not supported on your system" % plugin_name)
@ -52,21 +57,20 @@ class Manager(object):
log.exception(e)
continue
created_instances = []
for instance_info in instances_info:
log.debug("creating '%s' (%s)" % (instance_info.name, instance_info.type))
new_instance = plugin.create_instance(instance_info.name, instance_info.devices, instance_info.options)
created_instances.append(new_instance)
plugin.assign_free_devices()
plugin.initialize_instances()
self._instances.extend(created_instances)
for instance_info in instance_info_list:
plugin = plugins_by_name[instance_info.type]
if plugin is None:
continue
log.debug("creating '%s' (%s)" % (instance_info.name, instance_info.type))
new_instance = plugin.create_instance(instance_info.name, instance_info.devices, instance_info.options)
plugin.assign_free_devices(new_instance)
plugin.initialize_instance(new_instance)
self._instances.append(new_instance)
def destroy_all(self):
for plugin in self._plugins:
log.debug("cleaning plugin '%s'" % plugin.name)
plugin.cleanup()
for instance in self._instances:
log.debug("destroying instance %s" % instance.name)
instance.plugin.destroy_instance(instance)
del self._plugins[:]
del self._instances[:]
@ -93,5 +97,5 @@ class Manager(object):
# profile_switch is helper telling plugins whether the stop is due to profile switch
def stop_tuning(self, profile_switch = False):
for instance in self._instances:
for instance in reversed(self._instances):
instance.unapply_tuning(profile_switch)