test: assert delivered rate and concurrency match config - #735
Open
Bslabe123 wants to merge 1 commit into
Open
Conversation
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Bslabe123 The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Bslabe123
marked this pull request as ready for review
August 17, 2026 22:17
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Aug 18, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
August 18, 2026 18:19
9b8c938 to
f519f9a
Compare
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Aug 18, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Aug 19, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
August 19, 2026 20:17
f519f9a to
2a7f378
Compare
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Aug 26, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
August 26, 2026 15:50
2a7f378 to
5c075ef
Compare
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
August 26, 2026 17:48
5c075ef to
02a8372
Compare
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Aug 26, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
August 27, 2026 19:38
02a8372 to
e0d06c6
Compare
Sim-backed e2e for the stimulus side of the load generator: that the load actually offered matches the load that was configured. Nothing verified this before, although docs/loadgen.md states the concurrent load type "achieves the exact concurrency specified". Adds e2e/utils/load_shape.py with the reconstruction helpers (in-flight sweep line, closed-loop plateau window, arrival-process tolerance) so the worker matrix in kubernetes-sigs#632 can reuse them. Adds a test module with four sim-backed cases (constant and poisson rate stages, concurrency levels divisible and not divisible by num_workers) plus eight helper self-tests that prove the assertions can go red. Delivered concurrency is reconstructed from the raw per-request start and end timestamps, not read off load_summary["concurrency"], which reportgen copies straight from the stage config. Part of kubernetes-sigs#633.
Bslabe123
force-pushed
the
test/load-shape-accuracy-633
branch
from
September 3, 2026 20:30
e0d06c6 to
886419c
Compare
Bslabe123
added a commit
to Bslabe123/inference-perf
that referenced
this pull request
Sep 3, 2026
The absorber now records when each reply finished (done_s) alongside the arrival time and stops keeping its own in-flight counter. The parity test feeds those arrival/finish pairs to e2e/utils/load_shape.py: rate via observed_send_rate, concurrency via the sweep line and assert_delivered_concurrency (peak never above C, time-weighted plateau mean within half a slot), so there is one definition of each in the e2e tier. rate_rel_tol is gone from expected.yaml. Each tool declares its spacing pattern (tools.<tool>.arrival: constant|poisson) and the tolerance is rate_tolerance(num_requests, arrival). Case a rises from 40 requests at 8/s to 600 at 40/s, the smallest count at which the Poisson side earns a useful bound (16%), matching the load-shape accuracy test. Measured against the absorber: rate 40.01/s (5% budget), plateau mean 7.88 of 8 (half-slot budget); C-1 and C+1 both fail.
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.
Part of #633. Asserts for the first time that the load inference-perf actually offered matches the load it was configured with: achieved request rate against configured rate, and delivered in-flight concurrency against
concurrency_level.Row in #606: "Load-shape accuracy (#633)", sim tier.
Why this is needed
Every other e2e test checks the measurement side; nothing checks the stimulus side, which sweep silently depends on.
docs/loadgen.mdpromises "the exact concurrency specified"; unit tests cover only the split arithmetic of_set_worker_concurrency, not whether workers honour it over real sockets. A semaphore bug throttling toconcurrency_level - 1passes everything today.What the test does
llm-d-inference-simwith pinned per-request latencies. Deliberatelysim: against real vLLM these assertions would measure the server's capacity, not the load generator.e2e/utils/load_shape.pyfrom raw per-requeststart_time/end_timepairs, never from reportgen's summary numbers.countandrequested_rateexact; reportedsend_durationandachieved_ratemust equal the recomputation (rel 1e-9, so any drift is a reportgen bug); delivered rate within a tolerance derived from the arrival process.constant: gaps are rescaled to sum to exactlyduration, so the only stochastic term is the first gap,Exp(1)/nrelative,k = 12for ~1e-5 false failure.poisson: renewal time, CoV1/sqrt(n), 4 sigma. Both floored at 5% for jitter. At n=600: 5% and 16.3%; tightens by raising n, never by shrinking the multiplier.concurrency_level8 and 5, 2 workers each, so one split leaves a remainder): in-flight is a sweep line over starts and ends, ties resolved ends-before-starts. The plateau window[C-th earliest start, latest start]excludes ramp-up and drain by construction (request k cannot start until k-C finished). Delivered concurrency must never exceed C (exact) and must be within half a slot of C time-weighted (measured handoff deficit on the sim is about 0.04 slot, so 10x headroom while still failing a whole-slot deficit).load_summary["concurrency"]is asserted only as a wiring check, labelled as one (reportgen copies it off the stage config).achieved_rateis not asserted on concurrent stages, which main.py rewrites torate=num_requests, duration=1.C-1andC+1both raise, the tolerance function is checked at known values, the sweep line against hand-computed segments.Per the row's lane note, dispatch scheduling arithmetic stays unit level in #659; only what needs real processes and sockets is asserted here.
Status
Stands alone on
main(7bfbaed).Verified locally with
llm-d-inference-simv0.6.1: 12 passed for the new module (4 sim-backed, 8 self-tests), 109s serial, 64s at-n 4.pdm run validateclean; unit suite unaffected (889 passed, 15 skipped). Kill-mutant: dropping the concurrency slack to 0.001 fails both cases.Not yet verified: the CI runner. Tolerances have roughly 10x headroom over what was observed (constant 0.5% off a 5% budget, poisson 1.5% off 16.3%), but a merge-gating timing assertion earns its flake budget over repeated runs.
Limit of the oracle (in the module docstring): the timestamps are the client's own, so this catches a generator falling behind schedule, a semaphore admitting the wrong count, and a wrong reportgen rate, but not a timestamping bug. The #481 absorber records offered load server-side; once it lands this test can be retargeted at it without changing assertions.
Helpers live in
e2e/utils/load_shape.py, as #633 asks, so the #632 worker matrix can reuse them.