fetch payload of multiple datagrams at once - #651
Open
kazuho wants to merge 31 commits into
Open
Conversation
…ers are called `start`, `end`, `dst`
…place encryption so that payload for multiple QUIC packets can be read at once, then can be scatter-encrypted
…nd_emit` to return blocked
… packets to fulfill, it needs to return `0` to indicate that progress has been made. But we do not want the stream scheduler to call `quicly_send_stream` once more.
kazuho
commented
Jan 29, 2026
kazuho
force-pushed
the
kazuho/scatter-stream4
branch
from
January 29, 2026 07:59
5ee458a to
4b7df80
Compare
…ned to be non-NULL
…as indicated by the function can be certain that scatter mode would be used when possible and worthwhile
cli already serves files/sized-text bufferlessly (the flatten callbacks read
exactly the requested `len` per `on_send_emit`), so the size it is asked for
reflects how many datagrams quicly fused into a single read. Record the average
and maximum of that size and print it in the stats line, and add a t/e2e.t
subtest that downloads a multi-packet response and asserts the server's
emit-size-max far exceeds the MTU -- i.e. scatter actually engaged -- while also
checking the body is intact.
Also make SpawnedProcess::finalize re-readable (do not close the log handle) so
the subtest can read the server's stats and still let DESTROY run, guarding the
read with `if ($self->{logfh})` to match the pid handling and stay safe at
global destruction.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When on_send_emit sets *len to zero (the payload is not yet available), quicly_send_stream returns QUICLY_ERROR_SEND_EMIT_BLOCKED. The default scheduler already detaches the stream before sending it; now it also absorbs that signal and moves on, leaving the stream descheduled until the application reschedules it via quicly_stream_sync_sendbuf. A bufferless application can therefore use the default scheduler directly rather than having to supply its own. Update the on_send_emit doc-comment accordingly, and add a t/test.c subtest that covers the block -> deschedule -> reschedule -> deliver cycle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Problem: Up until now, the
on_send_emitcallback has been invoked for each STREAM frame being built. This has become a bottleneck, due to two reasons:preadfor each call toon_send_emit.Solution:
Earlier attempts (#609 and #648) tried to reduce the overhead by fetching the payload for multiple QUIC packets in one go—either via
preadv, or viapreadfollowed bymemmoveso the payload ends up exactly where it will be encrypted in place.The drawback of those approaches is that the payload has to be scattered per packet before encrypted, which is inefficient.
This PR takes a different approach. Assuming the buffer passed to
quicly_sendhas some extra space beyond the region where packets are built, it:When running at full speed,
quicly_sendtypically builds multiple packets in batch (often up to ten). Because the packet and frame construction regions overlap within the same buffer, the additional L1$ footprint due to the use of out-of-place encryption is minimized.Separately, this pull request allows the
on_send_emitcallback to return length of zero to indicate that payload is not immediately available, which causesquicly_send_streamto bail out with an error code ofQUICLY_ERROR_SEND_EMIT_BLOCKED. When using anon_send_emitcallback that behaves as such, the stream scheduler should handle the new error code and refrain from callingquicly_send_streamuntil the payload becomes available.