Skip to content

Conversation

@Watson1978
Copy link
Contributor

Currently, rb_decompress allocates a temporary buffer and copies the input string using ALLOC_N and memcpy. This overhead is significant, especially for large data, and doubles the memory usage during decompression.

benchmark

require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'zstd-ruby'
  gem 'benchmark-ips'
end

require 'securerandom'
large_data = SecureRandom.random_bytes(1024 * 1024 * 100)
compressed_data = Zstd.compress(large_data)

Benchmark.ips do |x|
  x.time = 15

  x.report("zstd decompress") do
    Zstd.decompress(compressed_data)
  end
end

before

$ ruby zstd.rb
ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [x86_64-linux]
Warming up --------------------------------------
     zstd decompress     1.000 i/100ms
Calculating -------------------------------------
     zstd decompress     11.148 (± 9.0%) i/s   (89.70 ms/i) -    167.000 in  15.085672s

after

$ ruby zstd.rb
ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [x86_64-linux]
Warming up --------------------------------------
     zstd decompress     2.000 i/100ms
Calculating -------------------------------------
     zstd decompress     20.890 (± 9.6%) i/s   (47.87 ms/i) -    312.000 in  15.015814s

Currently, `rb_decompress` allocates a temporary buffer and copies the input string using `ALLOC_N` and `memcpy`.
This overhead is significant, especially for large data, and doubles the memory usage during decompression.

## benchmark
```ruby
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'zstd-ruby'
  gem 'benchmark-ips'
end

require 'securerandom'
large_data = SecureRandom.random_bytes(1024 * 1024 * 100)
compressed_data = Zstd.compress(large_data)

Benchmark.ips do |x|
  x.time = 15

  x.report("zstd decompress") do
    Zstd.decompress(compressed_data)
  end
end
```

## before
```
$ ruby zstd.rb
ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [x86_64-linux]
Warming up --------------------------------------
     zstd decompress     1.000 i/100ms
Calculating -------------------------------------
     zstd decompress     11.148 (± 9.0%) i/s   (89.70 ms/i) -    167.000 in  15.085672s
```

## after
```
$ ruby zstd.rb
ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [x86_64-linux]
Warming up --------------------------------------
     zstd decompress     2.000 i/100ms
Calculating -------------------------------------
     zstd decompress     20.890 (± 9.6%) i/s   (47.87 ms/i) -    312.000 in  15.015814s
```
@SpringMT SpringMT merged commit 5146a1b into SpringMT:main Dec 26, 2025
7 checks passed
@SpringMT
Copy link
Owner

Thank you!

@Watson1978 Watson1978 deleted the performance branch December 26, 2025 12:22
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.

2 participants