Skip to content

base: stream HTTP and websocket payloads into the handler's buffer - #7266

Open
LalitMaganti wants to merge 1 commit into
dev/lalitm/zerocopy-2b-rpc-streamsfrom
dev/lalitm/zerocopy-3-httpserver
Open

base: stream HTTP and websocket payloads into the handler's buffer#7266
LalitMaganti wants to merge 1 commit into
dev/lalitm/zerocopy-2b-rpc-streamsfrom
dev/lalitm/zerocopy-3-httpserver

Conversation

@LalitMaganti

@LalitMaganti LalitMaganti commented Aug 28, 2026

Copy link
Copy Markdown
Member

This makes it such that instead of the HttpServer providing the buffer
for HTTP/Websocket payloads, it instead asks the handler for where they
would like the payload to be stored.

The flow looks like this: socket read -> HTTPServer reads the
headers/framing -> once it knows the size it calls OnHttpRequestBody or
OnWebsocketPayload depending on the message type -> the handler provides
the storage bytes -> httpserver reads into those provided buffers.

The motivation for this is that it removes one copy allowing for
"zero-copy" parsing and tokenization etc.

The motivation for this is multi-threaded trace processor which requires
fast-handoffs of buffers between threads and reducing the latency of the
parse path (because we're going to be adding latency by a cross thread
hop). This change is one step on that journey.

Because a payload is now read across several socket reads, more than one
can be in flight at a time, so every buffer the handler hands out has to
belong to the connection asking for it. RPC payloads go into that
connection's Rpc::Stream, added in the previous change; the bodies of
the non-RPC endpoints go into a per-connection buffer alongside it.
Sharing either across connections lets one connection's payload be
dispatched into another's, or freed under it when the buffer grows.

The origin check moves above the point where the body is requested, so a
request that is about to be refused with a 403 is never handed a payload
sink to write into.

The reservation is held in the connection's state between the two calls,
so a peer that disappears mid-payload gives it back explicitly rather
than leaving the tokenizer believing a write is still in flight.

@LalitMaganti
LalitMaganti requested a review from a team as a code owner August 28, 2026 01:33
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from c9f2336 to b4ab8ad Compare August 28, 2026 01:40
@primiano

Copy link
Copy Markdown
Member

Sry this needs some more commentary i'm a bit lost in trying to follow what the intended new usage of onWebsocket** is, before I even look into the code itself.

At very least the commit message (or the comments in the code) need to explain what you have in mind here.

@LalitMaganti

Copy link
Copy Markdown
Member Author

Sry this needs some more commentary i'm a bit lost in trying to follow what the intended new usage of onWebsocket** is, before I even look into the code itself.

The idea is that the caller provides the buffer for the httpserver to read the websocket message/http body payload into. This removes the need to first copy into the httpserver staging and then copy into another buffer.

Motivation is trace processor multi-threading which needs buffers which can move between threads.

I've changed the commit message, PTAL.

@LalitMaganti
LalitMaganti requested review from primiano and removed request for safayat-google August 28, 2026 10:25
Comment thread src/trace_processor/rpc/httpd.cc Outdated
Comment thread src/trace_processor/rpc/httpd.cc Outdated
Comment thread src/base/http/http_server.cc
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from b4ab8ad to 4aaa9c3 Compare August 28, 2026 14:30
@LalitMaganti
LalitMaganti changed the base branch from dev/lalitm/zerocopy-2-wasm to dev/lalitm/zerocopy-2b-rpc-streams August 28, 2026 14:39
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from 4aaa9c3 to a6f43ff Compare August 28, 2026 15:10
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from a6f43ff to ebf2df5 Compare August 28, 2026 15:30
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from ebf2df5 to 3bc0ff5 Compare August 28, 2026 15:32
@LalitMaganti

Copy link
Copy Markdown
Member Author

#7274 should have addressed the stream tearing problem completel leaving this CL focusing on just migrating the HTTP server to be zero copy. PTAL.

This makes it such that instead of the HttpServer providing the buffer
for HTTP/Websocket payloads, it instead asks the handler for where they
would like the payload to be stored.

The flow looks like this: socket read -> HTTPServer reads the
headers/framing -> once it knows the size it calls OnHttpRequestBody or
OnWebsocketPayload depending on the message type -> the handler provides
the storage bytes -> httpserver reads into those provided buffers.

The motivation for this is that it removes one copy allowing for
"zero-copy" parsing and tokenization etc.

The motivation for this is multi-threaded trace processor which requires
fast-handoffs of buffers between threads and reducing the latency of the
parse path (because we're going to be adding latency by a cross thread
hop). This change is one step on that journey.

Because a payload is now read across several socket reads, more than one
can be in flight at a time, so every buffer the handler hands out has to
belong to the connection asking for it. RPC payloads go into that
connection's Rpc::Stream, added in the previous change; the bodies of
the non-RPC endpoints go into a per-connection buffer alongside it.
Sharing either across connections lets one connection's payload be
dispatched into another's, or freed under it when the buffer grows.

The origin check moves above the point where the body is requested, so a
request that is about to be refused with a 403 is never handed a payload
sink to write into.

The reservation is held in the connection's state between the two calls,
so a peer that disappears mid-payload gives it back explicitly rather
than leaving the tokenizer believing a write is still in flight.
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/zerocopy-3-httpserver branch from 3bc0ff5 to 4044fdb Compare August 28, 2026 15:38
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