Skip to content

Speed up immediate unpack when freeze: true by 10%#396

Open
skipkayhil wants to merge 2 commits into
msgpack:masterfrom
skipkayhil:hm-skokvxlqtrxvuppu
Open

Speed up immediate unpack when freeze: true by 10%#396
skipkayhil wants to merge 2 commits into
msgpack:masterfrom
skipkayhil:hm-skokvxlqtrxvuppu

Conversation

@skipkayhil

Copy link
Copy Markdown
Contributor

Rename object_complete_symbol -> frozen

To use with other, non-symbol, pre-frozen objects.


Speed up immediate unpack when freeze: true by 10%

Since immediates are already frozen, we can skip over "maybe freeze"
behavior completely for those types.

ruby 4.0.2 (2026-03-17 revision d3da9fec82) +YJIT +PRISM [x86_64-linux]
Warming up --------------------------------------
             control     5.437k i/100ms
       frozen before     4.733k i/100ms
Calculating -------------------------------------
             control     54.830k (± 1.8%) i/s   (18.24 μs/i) -    277.287k in   5.057252s
       frozen before     49.078k (± 1.9%) i/s   (20.38 μs/i) -    246.116k in   5.014762s

Comparison:
 frozen after:    55009.0 i/s
      control:    54829.6 i/s - same-ish: difference falls within error
frozen before:    49078.3 i/s - 1.12x  slower
require 'msgpack'
require 'benchmark/ips'

data = []
100.times do
  data << rand(0..127)
  data << -rand(0..30)
  data << nil
  data << true
  data << false
  data << rand(0..65535)
end

packed = MessagePack.pack(data)

up_ctl = MessagePack::Unpacker.new(freeze: false)
up_frz = MessagePack::Unpacker.new(freeze: true)

Benchmark.ips do |x|
  x.report("control") { up_ctl.feed(packed); up_ctl.read }

  x.report("frozen #{ENV.fetch("STAGE", "after")}") { up_frz.feed(packed); up_frz.read }

  x.save!("/tmp/msgpack_un_freeze")

  x.compare!
end

To use with other, non-symbol, pre-frozen objects.
Since immediates are already frozen, we can skip over "maybe freeze"
behavior completely for those types.

```
ruby 4.0.2 (2026-03-17 revision d3da9fec82) +YJIT +PRISM [x86_64-linux]
Warming up --------------------------------------
             control     5.437k i/100ms
       frozen before     4.733k i/100ms
Calculating -------------------------------------
             control     54.830k (± 1.8%) i/s   (18.24 μs/i) -    277.287k in   5.057252s
       frozen before     49.078k (± 1.9%) i/s   (20.38 μs/i) -    246.116k in   5.014762s

Comparison:
 frozen after:    55009.0 i/s
      control:    54829.6 i/s - same-ish: difference falls within error
frozen before:    49078.3 i/s - 1.12x  slower
```

```ruby
require 'msgpack'
require 'benchmark/ips'

data = []
100.times do
  data << rand(0..127)
  data << -rand(0..30)
  data << nil
  data << true
  data << false
  data << rand(0..65535)
end

packed = MessagePack.pack(data)

up_ctl = MessagePack::Unpacker.new(freeze: false)
up_frz = MessagePack::Unpacker.new(freeze: true)

Benchmark.ips do |x|
  x.report("control") { up_ctl.feed(packed); up_ctl.read }

  x.report("frozen #{ENV.fetch("STAGE", "after")}") { up_frz.feed(packed); up_frz.read }

  x.save!("/tmp/msgpack_un_freeze")

  x.compare!
end
```
@skipkayhil skipkayhil changed the title Speed up immediate unpack when freeze: true Speed up immediate unpack when freeze: true by 10% Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant