From b8f279b8fb98e29931307247e7251528821bf803 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 30 Aug 2026 22:12:31 +0200 Subject: [PATCH] perf: stabilize the model registry signature across workers (#29264) The Redis-backed model registry skips its write when the content signature matches what is already stored. That skip has never worked across processes. Two of the values it hashes come out of Python sets, and set iteration order varies with each process's hash seed, so every worker computed a different signature for identical content and every worker rewrote the whole registry on every refresh. Sorting both makes the signature depend on content alone. Measured on a 120 model registry, 522 KiB serialized: a refresh whose content already matches drops from GET, HKEYS, HSET and SET at 5.1 ms to a single GET at 2.2 ms per worker, and the 522 KiB write leaves the wire entirely. Verified across 12 child processes with 12 distinct hash seeds: 12 different signatures before, 1 after. Filter execution order is unaffected, because the filter pipeline re-sorts by priority and id before running. --- backend/open_webui/utils/chat_variables.py | 2 +- backend/open_webui/utils/models.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/chat_variables.py b/backend/open_webui/utils/chat_variables.py index 5ff2e21b05..c1776f333f 100644 --- a/backend/open_webui/utils/chat_variables.py +++ b/backend/open_webui/utils/chat_variables.py @@ -112,7 +112,7 @@ def _safe_field(key: str, definition: dict[str, Any]) -> dict[str, Any]: 'type', } field = {'key': key} - for field_key in allowed_keys: + for field_key in sorted(allowed_keys): if field_key in definition: field[field_key] = definition[field_key] diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 1c648b7f38..717718cc99 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -374,6 +374,8 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) for filter_id in set(model.pop('filter_ids', [])) | global_filter_ids if filter_id in enabled_filter_ids ] + # Set order varies per process, and an unstable order defeats the RedisDict content signature. + filter_ids.sort() model['actions'] = [] for action_id in action_ids: