Skip to content

Commit 6bf285b

Browse files
Watson1978claude
andcommitted
Speed up decoding of oversized integers
Bigint.from_msgpack_ext rebuilt the integer by shifting and adding one 32-bit chunk at a time. Each step copies the whole growing bignum, so decoding was quadratic in the payload length (a 1 MiB ext payload took over 20 seconds). Convert the chunks to a hex string and parse it in a single String#to_i(16), which runs in linear time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4aa8bb9 commit 6bf285b

1 file changed

Lines changed: 3 additions & 7 deletions

File tree

‎lib/msgpack/bigint.rb‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module Bigint
55
# We split the bigint in 32bits chunks so that individual part fits into
66
# a MRI immediate Integer.
77
CHUNK_BITLENGTH = 32
8-
FORMAT = 'CL>*'
8+
CHUNK_FORMAT = 'L>*'
9+
FORMAT = "C#{CHUNK_FORMAT}"
910

1011
if Integer.instance_method(:[]).arity != 1 # Ruby 2.7 and newer
1112
# Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[]
@@ -56,12 +57,7 @@ def self.from_msgpack_ext(data)
5657
parts = data.unpack(FORMAT)
5758

5859
sign = parts.shift
59-
sum = parts.pop.to_i
60-
61-
parts.reverse_each do |part|
62-
sum = sum << CHUNK_BITLENGTH
63-
sum += part
64-
end
60+
sum = parts.reverse.pack(CHUNK_FORMAT).unpack1('H*').to_i(16)
6561

6662
sign == 0 ? sum : -sum
6763
end

0 commit comments

Comments
 (0)