Skip to content

Commit 5876f4a

Browse files
committed
Optimize Ext::Generator::State#configure
If we assume that most of the time the `opts` hash is small it's faster to go over the provided keys with a `case` than to test all possible keys one by one. Before: ``` == Encoding small nested array (121 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 156.832k i/100ms oj 209.769k i/100ms rapidjson 162.922k i/100ms Calculating ------------------------------------- json 1.599M (± 2.5%) i/s (625.34 ns/i) - 7.998M in 5.005110s oj 2.137M (± 1.5%) i/s (467.99 ns/i) - 10.698M in 5.007806s rapidjson 1.677M (± 3.5%) i/s (596.31 ns/i) - 8.472M in 5.059515s Comparison: json: 1599141.2 i/s oj: 2136785.3 i/s - 1.34x faster rapidjson: 1676977.2 i/s - same-ish: difference falls within error == Encoding small hash (65 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 216.464k i/100ms oj 661.328k i/100ms rapidjson 324.434k i/100ms Calculating ------------------------------------- json 2.301M (± 1.7%) i/s (434.57 ns/i) - 11.689M in 5.081278s oj 7.244M (± 1.2%) i/s (138.05 ns/i) - 36.373M in 5.021985s rapidjson 3.323M (± 2.9%) i/s (300.96 ns/i) - 16.871M in 5.081696s Comparison: json: 2301142.2 i/s oj: 7243770.3 i/s - 3.15x faster rapidjson: 3322673.0 i/s - 1.44x faster ``` After: ``` == Encoding small nested array (121 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 168.087k i/100ms oj 208.872k i/100ms rapidjson 149.909k i/100ms Calculating ------------------------------------- json 1.761M (± 1.1%) i/s (567.90 ns/i) - 8.909M in 5.059794s oj 2.144M (± 0.9%) i/s (466.37 ns/i) - 10.861M in 5.065903s rapidjson 1.692M (± 1.7%) i/s (591.04 ns/i) - 8.545M in 5.051808s Comparison: json: 1760868.2 i/s oj: 2144205.9 i/s - 1.22x faster rapidjson: 1691941.1 i/s - 1.04x slower == Encoding small hash (65 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 242.957k i/100ms oj 675.217k i/100ms rapidjson 355.040k i/100ms Calculating ------------------------------------- json 2.569M (± 1.5%) i/s (389.22 ns/i) - 12.877M in 5.013095s oj 7.128M (± 2.3%) i/s (140.30 ns/i) - 35.787M in 5.023594s rapidjson 3.656M (± 3.1%) i/s (273.50 ns/i) - 18.462M in 5.054558s Comparison: json: 2569217.5 i/s oj: 7127705.6 i/s - 2.77x faster rapidjson: 3656285.0 i/s - 1.42x faster ```
1 parent 69955a2 commit 5876f4a

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

lib/json/common.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,13 +576,12 @@ class << self
576576
# Sets or returns the default options for the JSON.dump method.
577577
# Initially:
578578
# opts = JSON.dump_default_options
579-
# opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
579+
# opts # => {:max_nesting=>false, :allow_nan=>true}
580580
attr_accessor :dump_default_options
581581
end
582582
self.dump_default_options = {
583583
:max_nesting => false,
584584
:allow_nan => true,
585-
:script_safe => false,
586585
}
587586

588587
# :call-seq:

lib/json/ext/generator/state.rb

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,35 @@ def configure(opts)
4343
end
4444
end
4545

46-
self.indent = opts[:indent] if opts.key?(:indent)
47-
self.space = opts[:space] if opts.key?(:space)
48-
self.space_before = opts[:space_before] if opts.key?(:space_before)
49-
self.array_nl = opts[:array_nl] if opts.key?(:array_nl)
50-
self.object_nl = opts[:object_nl] if opts.key?(:object_nl)
51-
self.max_nesting = opts[:max_nesting] || 0 if opts.key?(:max_nesting)
52-
self.depth = opts[:depth] if opts.key?(:depth)
53-
self.buffer_initial_length = opts[:buffer_initial_length] if opts.key?(:buffer_initial_length)
54-
self.allow_nan = opts[:allow_nan] if opts.key?(:allow_nan)
55-
self.ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
56-
57-
if opts.key?(:script_safe)
58-
self.script_safe = opts[:script_safe]
59-
elsif opts.key?(:escape_slash)
60-
self.script_safe = opts[:escape_slash]
46+
opts.each do |key, value|
47+
case key
48+
when :indent
49+
self.indent = value
50+
when :space
51+
self.space = value
52+
when :space_before
53+
self.space_before = value
54+
when :array_nl
55+
self.array_nl = value
56+
when :object_nl
57+
self.object_nl = value
58+
when :max_nesting
59+
self.max_nesting = value || 0
60+
when :depth
61+
self.depth = value
62+
when :buffer_initial_length
63+
self.buffer_initial_length = value
64+
when :allow_nan
65+
self.allow_nan = value
66+
when :ascii_only
67+
self.ascii_only = value
68+
when :script_safe, :escape_slash
69+
self.script_safe = value
70+
when :strict
71+
self.strict = value
72+
end
6173
end
6274

63-
self.strict = opts[:strict] if opts[:strict]
64-
6575
self
6676
end
6777

0 commit comments

Comments
 (0)