open-webui/backend
Classic298 b1bfc18762
perf: cache the serialized builtin tool spec instead of deep-copying it per request (#28860)
Every chat request hands each builtin tool a fresh copy of its cached spec, because callers mutate what they get. That copy was a full deepcopy of a nested dict, repeated per tool per message.

The builder now caches the spec already serialized, so a request only parses it back. Parsing is what produces the independent tree callers mutate, and the cached value becomes an immutable string, so a request can no longer reach the cached object at all.

Measured on CPython 3.12 with a 1.1 KB spec and 20 builtin tools per request:

| | before | after |
|---|---|---|
| stdlib json, the default | 276.2 us | 66.4 us |
| orjson | 279.5 us | 37.5 us |

Builtin specs are plain JSON by construction: pydantic normalizes every default before it reaches the schema, so a tuple, set, enum or datetime cannot appear in one, and an unserializable default is dropped rather than embedded.
2026-08-25 16:00:34 -04:00
..
data refac: mv backend files to /open_webui dir 2024-09-04 16:54:48 +02:00
open_webui perf: cache the serialized builtin tool spec instead of deep-copying it per request (#28860) 2026-08-25 16:00:34 -04:00
.dockerignore fix: litellm config issue 2024-02-24 22:35:11 -08:00
.gitignore refac 2024-09-06 04:59:20 +02:00
dev.sh perf: allow disabling websocket per-message-deflate (#28613) 2026-08-24 18:46:07 -04:00
requirements-min.txt perf: optional orjson JSON codec behind ENABLE_ORJSON (#27583) 2026-07-27 03:45:37 -04:00
requirements.txt chore: python-docx dep 2026-08-25 11:59:37 -04:00
start.sh perf: allow disabling websocket per-message-deflate (#28613) 2026-08-24 18:46:07 -04:00
start_windows.bat perf: allow disabling websocket per-message-deflate (#28613) 2026-08-24 18:46:07 -04:00