From b143664747cffed34d42a7cc5ee27081371970dc Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Sun, 4 Dec 2022 23:56:35 -0500 Subject: [PATCH] task: use exponential backoff algorithm to set thread count Tasks are often running longer than 5 seconds (especially extents with multiple references requiring copy operations), so the load tracking algorithm needs to average several samples over a longer period of time than 5 seconds. If the sample period is 60 seconds, we end up recomputing the original load average from current_load, so skip the rounding error and use the original load average value. Arguably the real fix is to break up the more complex extent operations over several downstream Task objects, but that's a more significant design change. Tweak the attack and decay rates so that threads are started a little more slowly, but still stopped rapidly when load spikes up. Remove the hysteresis to provide support for load average targets below 1, or with fractional components, with a PWM-like effect. Signed-off-by: Zygo Blaxell --- lib/task.cc | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/task.cc b/lib/task.cc index c33cf87..405cc97 100644 --- a/lib/task.cc +++ b/lib/task.cc @@ -499,17 +499,13 @@ namespace crucible { m_prev_loadavg = loadavg; - // Change the thread target based on the - // difference between current and desired load - // but don't get too close all at once due to rounding and sample error. - // If m_load_target < 1.0 then we are just doing PWM with one thread. - - if (m_load_target <= 1.0) { - m_thread_target = 1.0; - } else if (m_load_target - current_load >= 1.0) { - m_thread_target += (m_load_target - current_load - 1.0) / 2.0; - } else if (m_load_target < current_load) { - m_thread_target += m_load_target - current_load; + const double load_deficit = m_load_target - loadavg; + if (load_deficit > 0) { + // Load is too low, solve by adding another worker + m_thread_target += load_deficit / 3; + } else if (load_deficit < 0) { + // Load is too high, solve by removing all known excess tasks + m_thread_target += load_deficit; } m_load_stats = TaskMaster::LoadStats {