Conversation
Batch ready messages at a 32 KiB soft threshold to reduce per-message buffer and frame-processing overhead, following tonic's strategy. Flush completed messages when the source is pending, ends, or fails, while preserving node ownership and excluding partial encodings. Require linkedbytes 0.1.16 for into_bytes_mut().
Inline metadata makes Status large and can trigger result_large_err in downstream code using strict Clippy checks. Allocate metadata only when needed and avoid metadata copies during successful status checks and initial error-response parsing. Preserve public APIs, clone isolation, and explicitly reserved metadata capacity.
Identity compression and decompression consume the input without copying it to the output. Some(Identity) also sets the gRPC compressed flag even though the payload should be uncompressed. Preserve the payload and normalize Identity to uncompressed encoding. Test each codec with fresh input and buffers to avoid false positives from consumed input or leftover output.
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.
Motivation
Statusstores metadata inline, increasing its size. Downstream code returningResult<T, Status>can fail stricter Clippy checks because ofclippy::result_large_err. Successful status checks and initial error-response parsing also copy metadata unnecessarily.Some(Identity)messages as compressed.Solution
Streaming encoder
Add a private
EncodeStreamthat batches messages while the source is ready. It follows tonic's batching strategy, adapted toLinkedBytesnodes, with the same 32 KiB soft threshold.The threshold controls batching, not the size of individual messages. Completed messages are flushed when the source returns
Pending, ends, or yields an error. Compression is still per-message.The raw encoder stream continues after source errors but stops after encoding errors. An encoding error flushes completed messages and discards the partially encoded message.
The uncompressed path transfers nodes directly and moves the entire trailing buffer with
mem::take. Message prefixes are backfilled using node positions and offsets.The compression path uses
LinkedBytes::into_bytes_mut(), so the minimumlinkedbytesversion is raised to0.1.16. In0.1.15, the method is namedinto_bytesmut.Status metadata
Store metadata on demand as
Option<Box<MetadataMap>>rather than inline. The public API is unchanged. Clones keep independent metadata. When aMetadataMapis passed to a constructor, its reserved capacity is retained even if the map is empty.Successful status checks no longer copy metadata. Initial error responses transfer their already-owned headers using the same filtering rules.
Status::from_header_mapstill retains metadata when parsing borrowed headers.Remove the related
result_large_errsuppressions.Identity
Encode
Some(Identity)as uncompressed data with the compressed flag set to zero. The Identity branches incompressanddecompressnow append the input bytes to the output and consume the input.Give each algorithm fresh input and buffers in the consistency test, so consumed input or output from an earlier iteration cannot mask a failure.
Tests
codec::encode::tests::test_encode_streamPendingcodec::encode::tests::test_encode_pendingPendingcodec::encode::tests::test_encode_errorstatus::tests::{metadata, from_header_map, infer_grpc_status}codec::encode::tests::test_encode,codec::compression::tests::test_consistency_for_compressionReady-message streaming measurements
The benchmark compared the upstream and PR versions of the Volo server using tonic and Volo clients over loopback on the same Linux ECS instance: AMD EPYC 7T83, KVM, 8 vCPUs, Rust 1.98.1, release build with LTO.
The server used one worker with CPU affinity
[0]; the client used two workers with affinity[2, 4]. These were guest CPU masks, set before process startup and inherited by worker threads.Each stream provided 16 continuously ready messages with 256 B payloads. Concurrency was 32 or 128, with four connections and no TLS or compression. For each client and concurrency level, each version ran six times, with a 2-second warmup and an 8-second measurement window per run. The before/after run order was balanced.
The tonic-client runs used the same client binary across both server versions, built with
tonic 0.14.6,tonic-prost 0.14.6, andprost 0.14.4. In the Volo-client runs, both client and server switched to the matching upstream or PR version.The table reports the median of the per-run throughputs, in completed streams per second. Each run uses its actual elapsed time, including the time to finish in-flight streams.
These results are specific to the continuously ready, uncompressed streaming workload and the client/server settings above.