Skip to content

feat: default to AMPHP bidi streaming, optimized and multi-worker - #3

Merged
qcodr merged 2 commits into
mainfrom
fix/bidi-streaming-cancellation
Jun 27, 2026
Merged

feat: default to AMPHP bidi streaming, optimized and multi-worker#3
qcodr merged 2 commits into
mainfrom
fix/bidi-streaming-cancellation

Conversation

@qcodr

@qcodr qcodr commented Jun 27, 2026

Copy link
Copy Markdown
Owner

No description provided.

Retire Swoole from the examples, README, and live demo (it stays as an
alternative transport) and make AmpStreamingServer the default everywhere,
then cut the bidi transport's per-request cost and scale it across cores.

Migration to AMP as the default:
- examples/endpoint.php + tracing.php + bin/restate-serve now serve over
  AmpStreamingServer (bidi HTTP/2 h2c); amp-endpoint.php folded into endpoint.php
- docker-compose / Makefile / docker images: examples-endpoint runs the amp
  image; bidi verified live against Restate 1.5.2 (only V7 cancellation needs >=1.7)
- README: AMP featured as the default, Swoole/PSR-15/Lambda listed as
  alternatives; dropped the shepherd.dev (Psalm) badge

Transport optimization (greeter, 16-core host, Restate 1.5.2):
- TCP_NODELAY on the server socket + per-slice frame coalescing in
  AmpStreamTransport: 495 -> ~660 req/s (+35%), p50 89 -> 63 ms (amphp leaves
  Nagle on, which collides with delayed-ACK for a ~40 ms per-invocation stall)
- inline fast-path: a non-parking handler runs in the request fiber and returns
  one ReadableBuffer (no async task, no outbound Queue, zero extra event-loop
  hops); only a parked handler falls back to the streaming queue via the new
  SwitchableOutputSink. +15-22% single-worker, tighter tail
- multi-worker: listen($host, $port, $workers) pre-forks N processes that share
  the port via SO_REUSEPORT, lifting the single-event-loop ceiling. 16 workers
  reach 1470 req/s @-c200 and 1709 @-c400 (beats single-worker Swoole's ~1228),
  and the single-process -c400 collapse (123 req/s) is gone

Benchmarks: e2e harness parameterized by TRANSPORT (swoole|amp) with a compare
target; new bench-endpoint-amp + a transport comparison in docs/BENCHMARKS.md.

Tests: cover the inline fast-path (SwitchableOutputSink + StreamingInline:
completed / parked-resolve / EOF-while-parked suspension). 509 unit tests green.
@codecov-commenter

codecov-commenter commented Jun 27, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Codecov flagged 3 uncovered patch lines: the EOF-before-journal return in
InvocationDriver::tryStartInline and the null vm/fiber guard in
RequestProcessor::continueStreamingFromPark. Add two tests exercising both —
an inline attempt that ends before the journal is ready (empty completion) and
a mis-constructed parked result that must close the channel rather than
dereference null.
@qcodr
qcodr merged commit f2f6de5 into main Jun 27, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants