Fixes two bugs found during self-correction before publishing: - /stream used Flux.interval(), which ticks on its own wall-clock schedule independent of downstream demand and threw OverflowException under a slow subscriber; switched to Flux.range(), which has no independent production schedule and can never outrun demand. - The event-loop-starvation test's first cut used only 8 concurrent /cpu requests as background load, which drained through the 4 event-loop threads well inside the /io measurement window and produced an inconsistent, sometimes-inverted result across runs; raised to 60 concurrent requests (matching the CPU-bound benchmark's own concurrency) so the load actually occupies the event loop for the full window. Also adds StreamBackpressureTest, a StepVerifier proof that the /stream endpoint never emits ahead of its subscriber's outstanding requests.
17 lines
1.3 KiB
Plaintext
17 lines
1.3 KiB
Plaintext
/io latency while 60 concurrent CPU-bound requests run, 2 vCPU sandbox, Spring Boot 4.1.1 / JDK 25.0.4.1
|
|
========================================================================================================
|
|
/io alone (baseline, no concurrent CPU load) : total=20 success=20 wall=336ms p50=323ms p99=329ms
|
|
/io while 60x /cpu (naive) run concurrently : total=20 success=20 wall=486ms p50=452ms p99=467ms
|
|
/io while 60x /cpu-offloaded run concurrently : total=20 success=20 wall=398ms p50=377ms p99=387ms
|
|
|
|
This is the real cost of the naive endpoint, and it does not show up by benchmarking
|
|
/cpu in isolation: /io shares the same small event-loop pool with /cpu. With enough
|
|
concurrent CPU load to occupy all 4 event-loop threads for the full measurement
|
|
window (a first cut of this test used only 8 concurrent CPU requests, which drained
|
|
through the event loop in well under the /io window and produced an inconsistent,
|
|
sometimes-inverted result across runs -- fixed by raising the CPU load's own
|
|
concurrency, not by changing the assertion), naive /io latency is consistently and
|
|
substantially worse than both the undisturbed baseline and the offloaded case. At
|
|
higher production concurrency this is the exact mechanism behind a single CPU-heavy
|
|
endpoint silently degrading every other endpoint on the same Netty server.
|