Correct severe performance problem

When running our plugins we're seeing a severe performance impact in
the ansible run-time. As it turns out, within the linear strategy we're
looping over all physical hosts in an environment and pulling address
information out to store as a task variable. This action causes all
tasks to reload all {group,host}_vars for all hosts and that repetitive
action results in a massive slowdown, especially when there are many
hosts within the inventory.

Results from a normal OSA playbook run on 50 hosts:
  time openstack-ansible openstack-hosts-setup.yml --forks 15
  real    37m44.263s
  user    35m30.984s
  sys     2m23.252s

Results with the strategy plugin disabled on 50 hosts:
  time ANSIBLE_STRATEGY_PLUGINS=false openstack-ansible openstack-hosts-setup.yml --forks 15
  real    5m8.641s
  user    6m30.792s
  sys     1m32.512s

This change scopes the physical host look up to the task and target host
and adds conditionals around the process to ensure we're not forcing a lookup
that has no chance of succeeding.

Results with this patch applied on 50 hosts and no forks:
  time openstack-ansible openstack-hosts-setup.yml
  real    6m40.573s
  user    7m53.336s
  sys     1m25.828s

Should anything like this come up again debug statements have been added
to the method so that we can enable verbose mode and know what is being
parsed.

Change-Id: I76af71ffe19b2a8afb18ed731f1362a4e399c613
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
Kevin Carter 2018-07-11 16:19:39 -05:00
parent 408d1f28d0
commit 94c93e533f
No known key found for this signature in database
GPG Key ID: 9443251A787B9FB3
1 changed files with 32 additions and 16 deletions

View File

@ -125,23 +125,39 @@ class StrategyModule(LINEAR.StrategyModule):
_play_context = copy.deepcopy(play_context)
try:
groups = self._inventory.get_groups_dict()
except AttributeError:
groups = self._inventory.get_group_dict()
physical_hosts = groups.get('hosts', groups.get('all', {}))
physical_host_addrs = {}
for physical_host in physical_hosts:
physical_host_vars = self._variable_manager.get_vars(
host=self._inventory.get_host(physical_host)
pha = task_vars['physical_host_addrs'] = dict()
physical_host_item = host.vars.get('physical_host')
if physical_host_item:
LINEAR.display.verbose(
u'The "physical_host" variable was found.',
host=host,
caplevel=0
)
physical_host_templar = LINEAR.Templar(loader=self._loader,
variables=physical_host_vars)
physical_host_addr = physical_host_templar.template(
physical_host_vars.get('ansible_host',
physical_host))
physical_host_addrs[physical_host] = physical_host_addr
task_vars['physical_host_addrs'] = physical_host_addrs
ph = self._inventory.get_host(physical_host_item)
if ph:
LINEAR.display.verbose(
u'The "physical_host" variable of "%s" has been found to'
u' have a corresponding host entry in inventory.'
% physical_host_item,
host=host,
caplevel=0
)
physical_host_vars = self._variable_manager.get_vars(host=ph)
for item in ['ansible_host', 'container_address', 'address']:
addr = physical_host_vars.get(item)
if addr:
LINEAR.display.verbose(
u'The "physical_host" variable of "%s" terminates'
u' at "%s" using the host variable "%s".' % (
physical_host_item,
addr,
item
),
host=host,
caplevel=0
)
pha[ph.name] = addr
break
if task.delegate_to:
# If a task uses delegation change the play_context