diff options
author | Jean Boussier <[email protected]> | 2024-10-17 12:36:13 +0200 |
---|---|---|
committer | git <[email protected]> | 2024-10-17 11:35:33 +0000 |
commit | 0e2ac4658430ae5c8beba36e0b608902b3404879 (patch) | |
tree | 70086e6c478487232e3737eebec7eee340c12c0c | |
parent | a1c420c740c66206d92b0fd0f880f226a1592b5d (diff) |
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
```
-rw-r--r-- | ext/json/lib/json/common.rb | 3 | ||||
-rw-r--r-- | lib/json/ext/generator/state.rb | 44 |
2 files changed, 28 insertions, 19 deletions
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 95acd2ac4d..840c630fd5 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -576,13 +576,12 @@ module JSON # Sets or returns the default options for the JSON.dump method. # Initially: # opts = JSON.dump_default_options - # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false} + # opts # => {:max_nesting=>false, :allow_nan=>true} attr_accessor :dump_default_options end self.dump_default_options = { :max_nesting => false, :allow_nan => true, - :script_safe => false, } # :call-seq: diff --git a/lib/json/ext/generator/state.rb b/lib/json/ext/generator/state.rb index 09e31e7c57..4f9675d7b5 100644 --- a/lib/json/ext/generator/state.rb +++ b/lib/json/ext/generator/state.rb @@ -43,25 +43,35 @@ module JSON end end - self.indent = opts[:indent] if opts.key?(:indent) - self.space = opts[:space] if opts.key?(:space) - self.space_before = opts[:space_before] if opts.key?(:space_before) - self.array_nl = opts[:array_nl] if opts.key?(:array_nl) - self.object_nl = opts[:object_nl] if opts.key?(:object_nl) - self.max_nesting = opts[:max_nesting] || 0 if opts.key?(:max_nesting) - self.depth = opts[:depth] if opts.key?(:depth) - self.buffer_initial_length = opts[:buffer_initial_length] if opts.key?(:buffer_initial_length) - self.allow_nan = opts[:allow_nan] if opts.key?(:allow_nan) - self.ascii_only = opts[:ascii_only] if opts.key?(:ascii_only) - - if opts.key?(:script_safe) - self.script_safe = opts[:script_safe] - elsif opts.key?(:escape_slash) - self.script_safe = opts[:escape_slash] + opts.each do |key, value| + case key + when :indent + self.indent = value + when :space + self.space = value + when :space_before + self.space_before = value + when :array_nl + self.array_nl = value + when :object_nl + self.object_nl = value + when :max_nesting + self.max_nesting = value || 0 + when :depth + self.depth = value + when :buffer_initial_length + self.buffer_initial_length = value + when :allow_nan + self.allow_nan = value + when :ascii_only + self.ascii_only = value + when :script_safe, :escape_slash + self.script_safe = value + when :strict + self.strict = value + end end - self.strict = opts[:strict] if opts[:strict] - self end |