drpcwire: assemble packets into pooled buffers to drop a receive-path copy#59
Open
shubhamdhama wants to merge 2 commits into
Open
drpcwire: assemble packets into pooled buffers to drop a receive-path copy#59shubhamdhama wants to merge 2 commits into
shubhamdhama wants to merge 2 commits into
Conversation
Add a BufferPool backed by sync.Pool that is shared across all streams within a Manager. The ring buffer now obtains buffers from the pool on Enqueue and transfers ownership to the caller on Dequeue, which advances the tail immediately. This removes the two-step Dequeue/Done protocol and simplifies Close (no longer needs to wait for held buffers). The pool is a required parameter in the Stream constructor, created once per Manager and passed to all streams it creates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… copy Receiving a message used to copy its payload twice: PacketAssembler appended each frame into its own backing array, and the ring buffer's Enqueue then copied that array into a pooled buffer. The second copy existed only to move the data into a buffer the consumer could own. The assembler now takes its buffer from the shared BufferPool and assembles frames directly into it, then hands ownership of that buffer to the completed packet. Enqueue stores the pooled pointer as is, and RawRecv/MsgRecv return the buffer to the pool once the message is consumed. This removes one full copy per received message. To let ownership flow through the ring buffer, Packet.Data is now a *[]byte instead of []byte. BufferPool moves from drpcstream to drpcwire because the assembler lives in drpcwire and drpcwire cannot import drpcstream. NewPacketAssembler now requires a pool, and the manager passes its shared recvPool to both the stream assembler and the pending invoke-stream assembler. Every completed packet now holds a pooled buffer, so each path returns it. handlePacket enqueues message buffers and hands ownership to the consumer, and defers Put for control and error packets after their data is read. The manager Puts the buffer after decoding metadata, and after the invoke is consumed; the latter is safe because NewServerStream copies the rpc name out before pdone fires. Also drop SplitN, which had no remaining users. Stream writes split frames through SplitData directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a305254 to
f5edd92
Compare
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.
Receiving a message used to copy its payload twice: PacketAssembler appended each frame into its own backing array, and the ring buffer's Enqueue then copied that array into a pooled buffer. The second copy existed only to move the data into a buffer the consumer could own.
The assembler now takes its buffer from the shared BufferPool and assembles frames directly into it, then hands ownership of that buffer to the completed packet. Enqueue stores the pooled pointer as is, and RawRecv/MsgRecv return the buffer to the pool once the message is consumed. This removes one full copy per received message.
To let ownership flow through the ring buffer, Packet.Data is now a *[]byte instead of []byte. BufferPool moves from drpcstream to drpcwire because the assembler lives in drpcwire and drpcwire cannot import drpcstream. NewPacketAssembler now requires a pool, and the manager passes its shared recvPool to both the stream assembler and the pending invoke-stream assembler.
Every completed packet now holds a pooled buffer, so each path returns it. handlePacket enqueues message buffers and hands ownership to the consumer, and defers Put for control and error packets after their data is read. The manager Puts the buffer after decoding metadata, and after the invoke is consumed; the latter is safe because NewServerStream copies the rpc name out before pdone fires.
Also drop SplitN, which had no remaining users. Stream writes split frames through SplitData directly.