mirror of
https://github.com/open-webui/terminals.git
synced 2026-11-05 01:37:21 +00:00
[PR #43] [CLOSED] PERF/FIX: Reduce orchestrator CPU at high session counts #59
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
open-webui/terminals#59
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/open-webui/terminals/pull/43
Author: @Classic298
Created: 7/15/2026
Status: ❌ Closed
Base:
main← Head:perf-hotpath-upstream📝 Commits (2)
d3967d5Reduce orchestrator CPU at high session counts5da4999Merge branch 'main' into perf-hotpath-upstream📊 Changes
9 files changed (+239 additions, -42 deletions)
View changed files
📝
README.md(+4 -0)📝
dev.sh(+1 -1)📝
pyproject.toml(+6 -1)📝
terminals/backends/base.py(+36 -0)📝
terminals/cli.py(+4 -0)📝
terminals/config.py(+10 -0)📝
terminals/middleware.py(+30 -13)📝
terminals/routers/auth.py(+29 -0)📝
terminals/routers/proxy.py(+119 -27)📄 Description
Description
At ~500-600 concurrent terminals, the orchestrator process is permanently pinned
at 100% of one CPU core (it's a single asyncio process). We profiled a production
deployment with py-spy and eliminated the hot spots; the same load now runs at
~32% of one core (GIL contention dropped from 92% to 24%).
Performance changes:
(host, port)instead of a single sharedconnection pool. httpcore scans the entire pool on every request event, with a
readability syscall per idle keepalive connection — with hundreds of distinct
container origins in one pool this alone consumed ~69% of the event loop.
Stale origins are LRU-evicted and their sockets closed.
(
TERMINALS_WS_COMPRESSIONre-enables). Compressing every terminal frame inpure Python is a large per-frame cost for traffic that rarely leaves the host.
TERMINALS_STATUS_CACHE_TTLseconds (default 30,
0restores check-every-request), removing two Dockerinspects + JSON parsing per proxied request. On connection failure the proxy
invalidates the cache and re-resolves mid-request, so a dead container is
re-provisioned on retry instead of returning 502.
TERMINALS_TOKEN_CACHE_TTLseconds (default 60,
0disables) in JWT mode — previously one Open WebUIround trip per proxied request. Note: a revoked token stays usable up to TTL.
TERMINALS_ACCESS_LOG); each record walks thestack in the loguru intercept handler. Maintainers may prefer default
true—happy to flip.
RequestIdMiddlewarerewritten as pure ASGI (BaseHTTPMiddlewareaddsper-request task overhead).
Bug fixes found along the way:
active_ws_connectionsleaked on failed connect attempts (early returnsskipped the decrement).
InvalidHandshake, e.g. container still initializing)escaped the retry loop as unhandled exceptions.
.gitignorecontainsbuild/andhatchling excludes VCS-ignored files even when they match
includepatterns,so
terminals/frontend/buildwas missing frompip install .andGET /returned 401 in Docker images. Fixed by declaring it via
artifacts.Contributor License Agreement
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.