Virtual helm merge: offload CPU-bound merge to thread pool to unblock async event loop #35

Closed
opened 2026-05-01 23:44:34 +10:00 by unkinben · 0 comments
Owner

Performance Issue

The _merge_helm_indexes function is a CPU-bound operation (YAML parse + URL rewrite + dedup + YAML dump) called directly inside an async route handler. For a 19-member virtual repo, this took 38.5 seconds of wall time, blocking the entire uvicorn event loop for that duration.

During this time no other requests can be served on that worker.

Fix

Wrap the synchronous merge call in asyncio.get_event_loop().run_in_executor(None, ...) (or asyncio.to_thread in Python 3.9+) so it runs in a thread pool without blocking the event loop:

merged = await asyncio.to_thread(
    handler.merge, raw_indexes, used_members, used_configs, proxy_base
)

This is independent of issue #34 (CSafeLoader) and should be applied regardless — even a fast merge deserves not to block the event loop.

Expected Impact

Other requests continue to be served while a large virtual merge runs. No regression for small merges.

## Performance Issue The `_merge_helm_indexes` function is a CPU-bound operation (YAML parse + URL rewrite + dedup + YAML dump) called directly inside an async route handler. For a 19-member virtual repo, this took **38.5 seconds** of wall time, blocking the entire uvicorn event loop for that duration. During this time no other requests can be served on that worker. ## Fix Wrap the synchronous merge call in `asyncio.get_event_loop().run_in_executor(None, ...)` (or `asyncio.to_thread` in Python 3.9+) so it runs in a thread pool without blocking the event loop: ```python merged = await asyncio.to_thread( handler.merge, raw_indexes, used_members, used_configs, proxy_base ) ``` This is independent of issue #34 (CSafeLoader) and should be applied regardless — even a fast merge deserves not to block the event loop. ## Expected Impact Other requests continue to be served while a large virtual merge runs. No regression for small merges.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/artifactapi#35