Improve performance of including tasks into the play (#84445)

* Improve performance of including tasks into the play

PlayIterator.add_tasks is used to insert tasks from an include into the
play for particular host. It makes a copy of the current block including
the tasks within the block and inserts the new tasks from the include
into the copied block. But there is no need to make copies of tasks
within the block, what we want is a "shallow" copy of the block. This
PR changes that to copy the block excluding the tasks within.

On a contrived playbook with 50 include_role tasks, each role has 1 task,
running on 10 hosts the running time is reduced from ~55s to ~44s in my
environment.

ci_complete

* Add changelog
pull/84887/head
Martin Krizek 8 months ago committed by GitHub
parent 5280850130
commit e66aaa66a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,2 @@
bugfixes:
- Optimize the way tasks from within ``include_tasks``/``include_role`` are inserted into the play.

@ -598,28 +598,22 @@ class PlayIterator:
if state.tasks_child_state: if state.tasks_child_state:
state.tasks_child_state = self._insert_tasks_into_state(state.tasks_child_state, task_list) state.tasks_child_state = self._insert_tasks_into_state(state.tasks_child_state, task_list)
else: else:
target_block = state._blocks[state.cur_block].copy() target_block = state._blocks[state.cur_block].copy(exclude_tasks=True)
before = target_block.block[:state.cur_regular_task] target_block.block[state.cur_regular_task:state.cur_regular_task] = task_list
after = target_block.block[state.cur_regular_task:]
target_block.block = before + task_list + after
state._blocks[state.cur_block] = target_block state._blocks[state.cur_block] = target_block
elif state.run_state == IteratingStates.RESCUE: elif state.run_state == IteratingStates.RESCUE:
if state.rescue_child_state: if state.rescue_child_state:
state.rescue_child_state = self._insert_tasks_into_state(state.rescue_child_state, task_list) state.rescue_child_state = self._insert_tasks_into_state(state.rescue_child_state, task_list)
else: else:
target_block = state._blocks[state.cur_block].copy() target_block = state._blocks[state.cur_block].copy(exclude_tasks=True)
before = target_block.rescue[:state.cur_rescue_task] target_block.rescue[state.cur_rescue_task:state.cur_rescue_task] = task_list
after = target_block.rescue[state.cur_rescue_task:]
target_block.rescue = before + task_list + after
state._blocks[state.cur_block] = target_block state._blocks[state.cur_block] = target_block
elif state.run_state == IteratingStates.ALWAYS: elif state.run_state == IteratingStates.ALWAYS:
if state.always_child_state: if state.always_child_state:
state.always_child_state = self._insert_tasks_into_state(state.always_child_state, task_list) state.always_child_state = self._insert_tasks_into_state(state.always_child_state, task_list)
else: else:
target_block = state._blocks[state.cur_block].copy() target_block = state._blocks[state.cur_block].copy(exclude_tasks=True)
before = target_block.always[:state.cur_always_task] target_block.always[state.cur_always_task:state.cur_always_task] = task_list
after = target_block.always[state.cur_always_task:]
target_block.always = before + task_list + after
state._blocks[state.cur_block] = target_block state._blocks[state.cur_block] = target_block
elif state.run_state == IteratingStates.HANDLERS: elif state.run_state == IteratingStates.HANDLERS:
state.handlers[state.cur_handlers_task:state.cur_handlers_task] = [h for b in task_list for h in b.block] state.handlers[state.cur_handlers_task:state.cur_handlers_task] = [h for b in task_list for h in b.block]

@ -177,7 +177,7 @@ class Block(Base, Conditional, CollectionSearch, Taggable, Notifiable, Delegatab
def _dupe_task_list(task_list, new_block): def _dupe_task_list(task_list, new_block):
new_task_list = [] new_task_list = []
for task in task_list: for task in task_list:
new_task = task.copy(exclude_parent=True) new_task = task.copy(exclude_parent=True, exclude_tasks=exclude_tasks)
if task._parent: if task._parent:
new_task._parent = task._parent.copy(exclude_tasks=True) new_task._parent = task._parent.copy(exclude_tasks=True)
if task._parent == new_block: if task._parent == new_block:

Loading…
Cancel
Save