base: stream HTTP and websocket payloads into the handler's buffer - #7266
base: stream HTTP and websocket payloads into the handler's buffer#7266LalitMaganti wants to merge 1 commit into
Conversation
🎨 Perfetto UI Builds
|
c9f2336 to
b4ab8ad
Compare
|
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. |
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. |
b4ab8ad to
4aaa9c3
Compare
4aaa9c3 to
a6f43ff
Compare
a6f43ff to
ebf2df5
Compare
ebf2df5 to
3bc0ff5
Compare
|
#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.
3bc0ff5 to
4044fdb
Compare
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.