pub struct BytesGatherer { /* private fields */ }Expand description
A scatter-gather buffer that threads large blobs through the response pipeline by reference, eliminating application-layer copies for bulk data such as post bundles.
§Motivation
When serving a GetPostBundleV1 response the post bundle payload (potentially hundreds of KB,
already brotli-compressed on disk) was previously copied multiple times before reaching the network.
Then at the transport boundary the single Bytes was handed to HTTPS/TCP with no opportunity
for vectored writes.
BytesGatherer fixes this by threading large blobs through the entire response path by
reference. Small POD fields (header bytes, JSON metadata) accumulate into an internal
BytesMut scratchpad, while large payloads are attached with push_bytes — a refcount bump
only, no memcpy. At the transport boundary compact merges any adjacent small segments, sets
Content-Length, and HTTP/2 receives a stream of Bytes chunks as separate DATA frames.
**Net result for GetPostBundle, the hottest-path of Hashiverse: ** multiple application-layer copies of the post bundle → 0. One
kernel copy to the network card remains (unavoidable).
After compact(1024) the segment layout for a typical GetPostBundle response looks like:
Segment 0: [rpc_header (~300 B) + response_header (peers/token/counts) (~50 B) + flag (1 B)]
← merged by compact, one BytesMut flush
Segment 1: post_bundle Bytes (e.g. 500 KB)
← original Bytes from disk, zero copyHTTP/2 sends these as 2 DATA frames. TCP concatenates to 1 contiguous buffer via to_bytes.
Implementations§
Source§impl BytesGatherer
impl BytesGatherer
pub fn from_bytes(bytes: Bytes) -> Self
pub fn put_u8(&mut self, v: u8)
pub fn put_u16_le(&mut self, v: u16)
pub fn put_u16(&mut self, v: u16)
pub fn put_u32_le(&mut self, v: u32)
pub fn put_u32(&mut self, v: u32)
pub fn put_u64(&mut self, v: u64)
pub fn put_slice(&mut self, s: &[u8])
Sourcepub fn put_bytes(&mut self, bytes: Bytes)
pub fn put_bytes(&mut self, bytes: Bytes)
Push a large blob — flush accumulator first, store blob by reference (zero copy).
Sourcepub fn put_bytes_gatherer(&mut self, other: BytesGatherer)
pub fn put_bytes_gatherer(&mut self, other: BytesGatherer)
Merge another gatherer — zero copy for blobs; fast path if both are still assembling.
If other has no committed segments yet (all bytes are still in its scratchpad),
the scratchpad bytes are appended directly into self.current — no flush, no new segment.
Trait Implementations§
Source§impl Default for BytesGatherer
impl Default for BytesGatherer
Source§fn default() -> BytesGatherer
fn default() -> BytesGatherer
Auto Trait Implementations§
impl Freeze for BytesGatherer
impl RefUnwindSafe for BytesGatherer
impl Send for BytesGatherer
impl Sync for BytesGatherer
impl Unpin for BytesGatherer
impl UnsafeUnpin for BytesGatherer
impl UnwindSafe for BytesGatherer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more