Repository navigation
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A failed cross-frame refill can still retain and replay an exhausted FramedTransport buffer.
1 open issue
What changed in this PR
Releases exhausted input storage in Ruby transports so idle connections do not retain large consumed payloads.
Changes:
- Adds exhaustion cleanup to four transports.
- Adds ownership, failure-path, metadata, and HTTP/TCP round-trip regression coverage.
| File | Description |
|---|---|
| lib/rb/spec/http_client_spec.rb | Tests real HTTP response lifetime and failed requests. |
| lib/rb/spec/header_transport_spec.rb | Tests payload cleanup while preserving metadata and pipelined frames. |
| lib/rb/spec/base_transport_spec.rb | Adds shared lifetime and TCP regression tests. |
| lib/rb/lib/thrift/transport/http_client_transport.rb | Releases exhausted response storage. |
| lib/rb/lib/thrift/transport/header_transport.rb | Releases exhausted payload storage, preserving metadata. |
| lib/rb/lib/thrift/transport/framed_transport.rb | Adds cleanup across read entry points. |
| lib/rb/lib/thrift/transport/buffered_transport.rb | Adds cleanup across read entry points. |
Review effort: Balanced
Client: rb Release consumed input storage in BufferedTransport, FramedTransport, HeaderTransport and HTTPClientTransport without waiting for another read or response. Preserve unread data, returned strings and Header metadata. Add regression coverage for input ownership, EOF and error handling, pipelined frames and transport round trips. Co-Authored-By: OpenAI Codex (gpt-6.1-sol) <codex@openai.com>
kpumuk
force-pushed
the
rb-release-consumed-input
branch
from
October 18, 2026 21:30
330cb37 to
9f527c3
Compare
This branch has not been deployed
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.

BufferedTransport, FramedTransport, HeaderTransport and HTTPClientTransport retain their last input buffer after the caller consumes it. A long-lived idle transport can therefore keep a large frame or HTTP response alive until the next refill or response.
Release the backing storage when input is exhausted, including when a later read operation raises. Replace the backing string so returned data stays valid. Preserve unread and pipelined bytes, Header reply metadata, HTTP status and existing close/error behavior. Use a direct path for ordinary Buffered/Framed byte reads and StringIO#getbyte for buffered Header/HTTP bytes. Framed refills release the exhausted previous frame before attempting the next read. Regression coverage exercises ownership, read entry points, failures, unsigned bytes, frame transitions and real HTTP/TCP round trips.
Benchmarks
Ruby 4.0.7 / PRISM, aarch64 Linux, YJIT disabled, ordinary GC enabled. Workers were pinned to Linux virtual CPU 0; each workload ran separately, with three warmup batches per worker and a balanced rotating/reversed measurement order. Setup and explicit GC are outside timing. CPU pinning does not reserve a physical host core.
The following pure-Ruby microbenchmark compares master
926dcc971c97aa935f00bc98848352e905c4c755with that runtime plus the proposed transport changes. Each variant has 24 measured rounds. Byte batches repeat 262,144read_bytecalls six times; chunk batches repeat 8 MiB consumed in 16 KiBread_allcalls 24 times. Every read is checked. Values are median milliseconds per repetition; time delta is the ratio of the displayed medians.Buffered/Framed retain a small byte-read cost for prompt reclamation. Header/HTTP avoid temporary one-byte Strings: allocated objects per 262,144 byte reads fall from 262,164 to 22 and from 262,145 to 2, respectively. Chunk differences near one percent should be treated as noise-sensitive. HTTP input is a seeded StringIO response body; network/request processing is excluded.
A separate generated-struct benchmark isolates the byte-read optimization against the same input-reclamation patch before that optimization (
fixed), rather than against master. It decodes 128CompactProtoTestStructrecords per repetition, with two repetitions per batch and 12 paired rounds. Every decoded object is checked against the fixture. Both variants use this checkout's identical native extension and remaining runtime. The native Compact results are:These decoding changes are incremental gains within this patch, not total gains over master. The full decoding matrix also covered Binary and pure Ruby. This is one fixture on one CRuby environment, without network/application scheduling costs; balanced execution reduces order bias but does not rule out host/VM interference. The earlier seven-process timings are superseded by these measurements.
Benchmark commands, from
/thrift/src/lib/rbin the Linux container with this checkout mounted at/thrift/src, generated Ruby spec fixtures available, and its native extension built:Reproduction harness and source setup
The measured schedule also interleaved an experimental cached-index variant. It is reconstructed below only to reproduce the schedule; it is not included in this PR. The scripts write raw JSONL samples. The
fastvariant is the proposed change;fixedremoves only the byte-read optimization.Save as
/tmp/thrift-6434-options/fast.patch:Save as
/tmp/thrift-6434-options/loader.rb:Save as
/tmp/thrift-6434-options/bench_worker.rb:Save as
/tmp/thrift-6434-options/bench_run.rb: