From 3c3b3762a879c0814380c5dddac175365ce38454 Mon Sep 17 00:00:00 2001 From: Michel Van den Bergh Date: Thu, 15 Jan 2026 21:06:26 +0000 Subject: [PATCH] Improve run assignment. A test will get any worker at most half the time since a worker cannot work twice in a row on the same test, no matter what throughput is set. This is a problem for a test which has an arch filter for which there are few qualifying workers. Then its actual throughput will be substantially below its requested throughput. We propose to correct this by sorting runs according to the following key (lexicographic ordering, lower is better) ======================================================== -run["args"]["priority"], run["cores"] > 0, (run["cores"] + (3/2 if str(run["_id"]) == last_run_id else 1/2) * max_threads) / run["args"]["itp"], ======================================================== In the last line we have readded the number of cores by this worker that were freed when the last task on this run finished. This ensures that the current worker does not automatically gets the previous run again, but it also does not prevent it in case run["cores"] is low compared to the requested throughput. By comparison the current key is: ======================================================== -run["args"]["priority"], str(run["_id"]) == last_run_id, run["cores"] > 0, (run["cores"] + max_threads / 2) / run["args"]["itp"], ======================================================== This means a different run is always preferred, unless there is no other possibility. --- server/fishtest/rundb.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/server/fishtest/rundb.py b/server/fishtest/rundb.py index c6ca9eca7..63e19d362 100644 --- a/server/fishtest/rundb.py +++ b/server/fishtest/rundb.py @@ -1107,17 +1107,22 @@ def sync_request_task(self, worker_info): # Now we sort the list of unfinished runs according to priority. last_run_id = self.worker_runs.get(my_name, {}).get("last_run", None) - def priority(run): # lower is better + def priority(run): + # A penalty term for working on the same run again. This amounts to adding the number + # of cores that were freed by this worker when the previous task finished. + # The added 1/2 * max_threads is to mitigate granularity issues with large core workers. + repeat_penalty = ( + 3 / 2 if str(run["_id"]) == last_run_id else 1 / 2 + ) * max_threads + + # lower is better return ( # Always consider the higher priority runs first -run["args"]["priority"], - # Try to avoid repeatedly working on the same test - str(run["_id"]) == last_run_id, # Make sure all runs at this priority level get _some_ cores run["cores"] > 0, # Try to match run["args"]["itp"]. - # Add max_threads/2 to mitigate granularity issues with large core workers. - (run["cores"] + max_threads / 2) / run["args"]["itp"], + (run["cores"] + repeat_penalty) / run["args"]["itp"], ) # Use a local copy of (the sorted) unfinished runs list so that it does