[
https://issues.apache.org/jira/browse/THRIFT-6149?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Dmytro Shteflyuk resolved THRIFT-6149.
--------------------------------------
Fix Version/s: 0.25.0
Resolution: Fixed
> Ruby Binary and Compact protocols should avoid decoding skipped strings
> -----------------------------------------------------------------------
>
> Key: THRIFT-6149
> URL: https://issues.apache.org/jira/browse/THRIFT-6149
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Library
> Reporter: Dmytro Shteflyuk
> Assignee: Dmytro Shteflyuk
> Priority: Major
> Fix For: 0.25.0
>
> Time Spent: 40m
> Remaining Estimate: 0h
>
> h3. Problem
> When generated Ruby code encounters an unknown field with Thrift type
> {{STRING}}, {{BaseProtocol#skip}} reads it through {{read_string}}. For the
> Binary and Compact protocols, this first consumes the value as binary data
> and then constructs a UTF-8 string even though the value is immediately
> discarded.
> Skipping should consume the wire value without performing representation work
> that cannot affect the result. JSON must retain its string-reading behavior
> because JSON strings and binary values have different wire representations.
> h3. Client impact
> Ruby clients and servers skip unknown fields when communicating across schema
> versions. Messages containing unknown string fields therefore create an
> unnecessary temporary string for every skipped value and spend additional
> time applying string encoding semantics.
> The overhead scales with the number of skipped values. A focused benchmark
> using 100,000 128-byte strings observed one fewer allocation per skipped
> value and lower skip time for Binary and Compact protocols when consuming the
> raw bytes directly. The wire format and decoded values of known fields are
> unaffected.
> h3. Reproduction
> From {{lib/rb}}, run:
> {code:bash}
> bundle exec ruby -Ilib -Iext <<'RUBY'
> require "thrift"
> class TrackingBinaryProtocol < Thrift::BinaryProtocol
> attr_reader :reads
> def initialize(transport)
> super
> @reads = []
> end
> def read_string
> @reads << :string
> super
> end
> def read_binary
> @reads << :binary
> super
> end
> end
> transport = Thrift::MemoryBufferTransport.new
> protocol = TrackingBinaryProtocol.new(transport)
> protocol.write_string("value")
> protocol.skip(Thrift::Types::STRING)
> puts protocol.reads.join(" -> ")
> RUBY
> {code}
> Testing on master commit {{9b10484ca7687af6cc67567df9d457d0f031748e}}
> produces:
> {code}
> string -> binary
> {code}
> The skipped value enters the string-decoding path before its underlying
> binary bytes are consumed.
> h3. Expected behavior
> Binary and Compact protocols should consume skipped {{STRING}} values through
> their raw binary readers, avoiding unnecessary string conversion. JSON and
> custom protocols should retain the existing {{read_string}} contract unless
> they explicitly specialize skipped-string handling.
> Header and decorated protocols should preserve the behavior of their selected
> or wrapped protocol. Skipping must consume exactly the same wire bytes as
> before and must not change handling of known fields.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)