From: "jhawthorn (John Hawthorn) via ruby-core" Date: 2025-04-18T05:26:42+00:00 Subject: [ruby-core:121682] [Ruby Bug#19288] Ractor JSON parsing significantly slower than linear parsing Issue #19288 has been updated by jhawthorn (John Hawthorn). Status changed from Open to Closed I've made a couple changes which should improve this. This is a bit of an odd benchmark as the keys are always random (which I think would be quite uncommon in real JSON parsing situations). But this makes it an interesting benchmark for some worst case behaviours. The two things this benchmark is exercising, as others have pointed out, is float parsing and insertion into the fstring table. The first change is https://github.com/ruby/ruby/pull/12991, which removes a spinlock in `dtoa.c` for bignum memory management (Balloc/Bfree). The second change is https://bugs.ruby-lang.org/issues/21268 / https://github.com/ruby/ruby/pull/12921, which I've just merged (NB. it **isn't** in preview1). With these two I believe the main bottlenecks of this benchmark have been removed. Though performance can always be improved, these are now faster under Ractors than serial. The main contention is now GC pressure caused by the JSON being parsed (in particular the random string keys, I would expect a more reasonable set of JSON to perform even better). --- **Original benchmark** ``` Serial - Ruby 3.4.2 0.995186 0.030131 1.025317 ( 1.025439) Serial - Ruby master@3a29e835e69187330bb3fee035f1289561de5dad 0.933650 0.014119 0.947769 ( 0.947780) Ractors - Ruby 3.4.2 10.875507 1.600797 12.476304 ( 3.380926) Ractors - Ruby master@3a29e835e69187330bb3fee035f1289561de5dad 1.490369 0.192624 1.682993 ( 0.749747) ``` **Eregon's improved benchmark - with shareable objects** ``` Serial - Ruby 3.4.2 0.982018 0.035003 1.017021 ( 1.017816) Serial - Ruby master@3a29e835e69187330bb3fee035f1289561de5dad 0.981966 0.026635 1.008601 ( 1.008593) Ractors - Ruby 3.4.2 12.232766 1.772653 14.005419 ( 3.578559) Ractors - Ruby master@3a29e835e69187330bb3fee035f1289561de5dad 1.301200 0.122725 1.423925 ( 0.470395) ``` **Luke-gru's Benchmark - with no send/recv** ``` Benchmark 1: ruby 3.4.2 serial Time (mean �� ��): 459.4 ms �� 10.5 ms [User: 449.8 ms, System: 8.8 ms] Range (min ��� max): 450.7 ms ��� 478.2 ms 10 runs Benchmark 2: ruby master serial Time (mean �� ��): 391.2 ms �� 60.4 ms [User: 381.7 ms, System: 8.5 ms] Range (min ��� max): 220.0 ms ��� 419.0 ms 10 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 3: ruby 3.4.2 ractors Time (mean �� ��): 2.258 s �� 0.685 s [User: 13.585 s, System: 0.367 s] Range (min ��� max): 0.310 s ��� 2.484 s 10 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 4: ruby master ractors Time (mean �� ��): 191.2 ms �� 13.8 ms [User: 547.1 ms, System: 110.3 ms] Range (min ��� max): 144.3 ms ��� 201.5 ms 14 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Summary ruby master ractors ran 2.05 �� 0.35 times faster than ruby master serial 2.40 �� 0.18 times faster than ruby 3.4.2 serial 11.81 �� 3.68 times faster than ruby 3.4.2 ractors ``` ---------------------------------------- Bug #19288: Ractor JSON parsing significantly slower than linear parsing https://bugs.ruby-lang.org/issues/19288#change-112734 * Author: maciej.mensfeld (Maciej Mensfeld) * Status: Closed * ruby -v: ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-linux] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- a simple benchmark: ```ruby require 'json' require 'benchmark' CONCURRENT = 5 RACTORS = true ELEMENTS = 100_000 data = CONCURRENT.times.map do ELEMENTS.times.map do { rand => rand, rand => rand, rand => rand, rand => rand }.to_json end end ractors = CONCURRENT.times.map do Ractor.new do Ractor.receive.each { JSON.parse(_1) } end end result = Benchmark.measure do if RACTORS CONCURRENT.times do |i| ractors[i].send(data[i], move: false) end ractors.each(&:take) else # Linear without any threads data.each do |piece| piece.each { JSON.parse(_1) } end end end puts result ``` Gives following results on my 8 core machine: ```shell # without ractors: 2.731748 0.003993 2.735741 ( 2.736349) # with ractors 12.580452 5.089802 17.670254 ( 5.209755) ``` I would expect Ractors not to be two times slower on the CPU intense work. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/