From: "drbrain (Eric Hodel)" Date: 2012-06-27T06:47:58+09:00 Subject: [ruby-core:45899] [ruby-trunk - Feature #6615] Release GVL in zlib when calling inflate() or deflate() Issue #6615 has been updated by drbrain (Eric Hodel). =begin This benchmarks inflates 100,000 1000byte deflate strings. 1000 bytes is smaller than the default Zlib buffer size, so use of realloc vs REALLOC_N should not matter. Code: require 'zlib' require 'benchmark' r = Random.new 0 file_count = 100_000 deflated = (0..file_count).map do input = r.bytes 1000 Zlib::Deflate.deflate input end times = Benchmark.measure do deflated.each do |input| Zlib::Inflate.inflate input end end puts times Without patch: $ for f in `jot 5`; do ruby20 test.rb; done 0.810000 0.060000 0.870000 ( 0.864994) 0.800000 0.050000 0.850000 ( 0.863737) 0.800000 0.060000 0.860000 ( 0.851056) 0.830000 0.060000 0.890000 ( 0.887332) 0.810000 0.060000 0.870000 ( 0.866989) With patch: $ for f in `jot 5`; do make runruby; done 0.780000 0.060000 0.840000 ( 0.851944) 0.800000 0.060000 0.860000 ( 0.865989) 0.770000 0.050000 0.820000 ( 0.823333) 0.770000 0.060000 0.830000 ( 0.828246) 0.760000 0.060000 0.820000 ( 0.828063) Slight decrease in time. =end ---------------------------------------- Feature #6615: Release GVL in zlib when calling inflate() or deflate() https://bugs.ruby-lang.org/issues/6615#change-27499 Author: drbrain (Eric Hodel) Status: Open Priority: Normal Assignee: Category: ext Target version: 2.0.0 This patch switches from zstream_run from using rb_thread_schedule() to rb_thread_blocking_region(). I don't see a way to safely interrupt deflate() or inflate() so the unblocking function is empty. This patch should allow use of output buffer sizes larger than 16KB. I suspect 16KB was chosen to allow reasonable context-switching time for ruby 1.8 and earlier. A larger buffer size would reduce GVL contention when processing large streams. An alternate way to reduce GVL contention would be to move zstream_run's loop outside the GVL, but some manual allocation would be required as currently the loop uses a ruby String as the output buffer. -- http://bugs.ruby-lang.org/