feat(loadtest): add USE_SYNC to benchmark the blocking client#821
Open
jrvb-rl wants to merge 2 commits into
Open
feat(loadtest): add USE_SYNC to benchmark the blocking client#821jrvb-rl wants to merge 2 commits into
jrvb-rl wants to merge 2 commits into
Conversation
USE_SYNC=1 drives devboxes.create through the blocking Runloop client on a ThreadPoolExecutor instead of async AsyncRunloop + asyncio. The sync worker pool is capped at min(REQUEST_COUNT, CONCURRENCY) with CONCURRENCY defaulting to 5000, since one-thread-per-request is infeasible at high counts and real socket concurrency is FD-bound anyway. Works with USE_HTTP2 for both h1 and h2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The blocking client is GIL-bound, so more worker threads add contention without raising throughput. Measured against the dev cluster at 20k HTTP/1.1 requests, a 500-worker pool beat 5000 on throughput (260 vs 199 req/s) with ~10x lower p50 latency (1.6s vs 16.9s). Document the rationale in the module docstring and README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
✅ Reflex agent status: Completed The agent completed its work. This PR was created by Reflex. This comment updates in place as the agent works. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
USE_SYNCtoloadtest/loadtest.pyso the harness can benchmark the blockingRunloopclient (driven by aThreadPoolExecutor) in addition to the asyncAsyncRunloopclient. Works with the existingUSE_HTTP2toggle, so the harness now covers async/sync × HTTP/1.1/HTTP/2.The TS SDK has no synchronous client (Node has no blocking HTTP client), so
USE_SYNCis Python-only; the TS harness stays async and appears as N/A in the sync rows below.Sync concurrency model
The blocking client can't use
asyncio.gather, so a burst is driven by a thread pool capped atworkers = min(REQUEST_COUNT, CONCURRENCY).CONCURRENCYdefaults to 500. The blocking client is GIL-bound, so more worker threads add contention without raising throughput. Measured at 20 000 HTTP/1.1 requests against dev, a 500-worker pool beat a 5000-worker pool — 260 vs 199 req/s with ~10× lower p50 latency (1.6 s vs 16.9 s). Rationale is documented in the module docstring and README.Test setup
api.runloop.pro), all requests hit the nonexistent blueprint → HTTP400, no devboxes created.ok= HTTP 400 (request reached the server);net_err= transport failure (surfaced via the new error breakdown).Results — Python
loadtest.py(async vs sync)Sync rows use the shipped default
CONCURRENCY=500(worker count =min(REQUEST_COUNT, 500)).HTTP/2
HTTP/1.1
Results — TS
loadtest.ts(async only)Findings
h2/httpcore stack is CPU/GIL-bound, not server-bound. At 20 000, TS HTTP/2 is ~27× Python's.Connection errorat every scale (even 200 threads). The high "throughput" there is fast failures, not work done. Sync + HTTP/1.1 is unaffected (socket-per-request; nothing to race on), and async + HTTP/2 is fine (the event loop coordinates waiters on the pending connection). Recommendation: use the async client for HTTP/2, or HTTP/1.1 if you need the sync client concurrently.max_connections=None) fires 20 000 simultaneous connects and never converges; the sync thread-ramp self-throttles and completes; TS completes but sheds 4622 requests to FD exhaustion. This is the FD-exhaustion case the harness already warns about.Also included
USE_SYNC/CONCURRENCYinloadtest/README.md.🤖 Generated with Claude Code
Reflex session: https://reflex.runloop.ai/orgs/runloop/agents/agt_4Sg729tM9zLk7ayz20XNib