diff --git a/lib/ansible/plugins/callback/cgroup_perf_recap.py b/lib/ansible/plugins/callback/cgroup_perf_recap.py index 2e8b6adbf9b..d9897756c82 100644 --- a/lib/ansible/plugins/callback/cgroup_perf_recap.py +++ b/lib/ansible/plugins/callback/cgroup_perf_recap.py @@ -46,6 +46,26 @@ DOCUMENTATION = ''' ini: - section: callback_cgroup_perf_recap key: cpu_poll_interval + memory_poll_interval: + description: Interval between memory polling for determining memory usage. A lower value may produce inaccurate + results, a higher value may not be short enough to collect results for short tasks. + default: 0.25 + type: float + env: + - name: CGROUP_MEMORY_POLL_INTERVAL + ini: + - section: callback_cgroup_perf_recap + key: memory_poll_interval + pid_poll_interval: + description: Interval between PID polling for determining PID count. A lower value may produce inaccurate + results, a higher value may not be short enough to collect results for short tasks. + default: 0.25 + type: float + env: + - name: CGROUP_PID_POLL_INTERVAL + ini: + - section: callback_cgroup_perf_recap + key: pid_poll_interval display_recap: description: Controls whether the recap is printed at the end, useful if you will automatically process the output files @@ -158,6 +178,10 @@ class BaseProf(with_metaclass(ABCMeta, threading.Thread)): class MemoryProf(BaseProf): """Python thread for recording memory usage""" + def __init__(self, path, poll_interval=0.25, obj=None, writer=None): + super(MemoryProf, self).__init__(path, obj=obj, writer=writer) + self._poll_interval = poll_interval + def poll(self): with open(self.path) as f: val = int(f.read().strip()) / 1024**2 @@ -169,7 +193,7 @@ class MemoryProf(BaseProf): except ValueError: # We may be profiling after the playbook has ended self.running = False - time.sleep(0.01) + time.sleep(self._poll_interval) class CpuProf(BaseProf): @@ -197,6 +221,10 @@ class CpuProf(BaseProf): class PidsProf(BaseProf): + def __init__(self, path, poll_interval=0.25, obj=None, writer=None): + super(PidsProf, self).__init__(path, obj=obj, writer=writer) + self._poll_interval = poll_interval + def poll(self): with open(self.path) as f: val = int(f.read().strip()) @@ -208,7 +236,7 @@ class PidsProf(BaseProf): except ValueError: # We may be profiling after the playbook has ended self.running = False - time.sleep(0.01) + time.sleep(self._poll_interval) def csv_writer(writer, timestamp, task_name, task_uuid, value): @@ -280,6 +308,8 @@ class CallbackModule(CallbackBase): super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct) cpu_poll_interval = self.get_option('cpu_poll_interval') + memory_poll_interval = self.get_option('memory_poll_interval') + pid_poll_interval = self.get_option('pid_poll_interval') self._display_recap = self.get_option('display_recap') control_group = to_bytes(self.get_option('control_group'), errors='surrogate_or_strict') @@ -320,9 +350,9 @@ class CallbackModule(CallbackBase): return self._profiler_map = { - 'memory': partial(MemoryProf, mem_current_file), + 'memory': partial(MemoryProf, mem_current_file, poll_interval=memory_poll_interval), 'cpu': partial(CpuProf, cpu_usage_file, poll_interval=cpu_poll_interval), - 'pids': partial(PidsProf, pid_current_file), + 'pids': partial(PidsProf, pid_current_file, poll_interval=pid_poll_interval), } write_files = self.get_option('write_files')