ruby / json

JSON implementation for Ruby
https://ruby.github.io/json
Other
704 stars 333 forks source link

Release 2.8.0 #693

Closed casperisfine closed 2 weeks ago

casperisfine commented 2 weeks ago

I can still see a lot of inefficiencies in ext/parser/parser.rl, but it mostly has to do with how the state machine is implemented, so it might require almost full rewrite.

In the meantime the parser performance progressed enough since 2.7.2 that I'm satisfied enough to not delay the 2.8.0 further, aside from some extra testing. If a brand new parser has to be implemented, that will be for 3.0.

json is now faster than oj on all three macro-benchmarks, and on par with Oj::Parser. It also performs very well on micro-benchmarks. Full parser benchmark results: https://gist.github.com/casperisfine/cf4b3a0594fae24b7d0eb93daaf3841a

== Parsing activitypub.json (58160 bytes)
ruby 3.4.0dev (2024-11-06T07:59:09Z precompute-hash-wh.. 7943f98a8a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
          json 2.7.2   638.000 i/100ms
                  oj   798.000 i/100ms
          Oj::Parser   948.000 i/100ms
           rapidjson   631.000 i/100ms
Calculating -------------------------------------
          json 2.7.2      6.423k (± 1.3%) i/s  (155.70 μs/i) -     32.538k in   5.067149s
                  oj      7.989k (± 1.0%) i/s  (125.17 μs/i) -     40.698k in   5.094544s
          Oj::Parser      9.472k (± 1.3%) i/s  (105.58 μs/i) -     47.400k in   5.005119s
           rapidjson      6.354k (± 1.1%) i/s  (157.37 μs/i) -     32.181k in   5.064962s

Comparison:
          json 2.8.0:     9510.0 i/s
          Oj::Parser:     9471.9 i/s - same-ish: difference falls within error
                  oj:     7989.4 i/s - 1.19x  slower
          json 2.7.2:     6422.5 i/s - 1.48x  slower
           rapidjson:     6354.5 i/s - 1.50x  slower

== Parsing twitter.json (567916 bytes)
ruby 3.4.0dev (2024-11-06T07:59:09Z precompute-hash-wh.. 7943f98a8a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
          json 2.7.2    52.000 i/100ms
                  oj    64.000 i/100ms
          Oj::Parser    76.000 i/100ms
           rapidjson    57.000 i/100ms
Calculating -------------------------------------
          json 2.7.2    526.860 (± 3.8%) i/s    (1.90 ms/i) -      2.652k in   5.042680s
                  oj    631.234 (± 1.7%) i/s    (1.58 ms/i) -      3.200k in   5.070973s
          Oj::Parser    764.354 (± 3.5%) i/s    (1.31 ms/i) -      3.876k in   5.077736s
           rapidjson    579.085 (± 2.8%) i/s    (1.73 ms/i) -      2.907k in   5.024620s

Comparison:
          json 2.8.0:      884.0 i/s
          Oj::Parser:      764.4 i/s - 1.16x  slower
                  oj:      631.2 i/s - 1.40x  slower
           rapidjson:      579.1 i/s - 1.53x  slower
          json 2.7.2:      526.9 i/s - 1.68x  slower

== Parsing citm_catalog.json (1727030 bytes)
ruby 3.4.0dev (2024-11-06T07:59:09Z precompute-hash-wh.. 7943f98a8a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
          json 2.7.2    30.000 i/100ms
                  oj    35.000 i/100ms
          Oj::Parser    45.000 i/100ms
           rapidjson    40.000 i/100ms
Calculating -------------------------------------
          json 2.7.2    304.584 (± 3.3%) i/s    (3.28 ms/i) -      1.530k in   5.029021s
                  oj    358.572 (± 0.8%) i/s    (2.79 ms/i) -      1.820k in   5.076123s
          Oj::Parser    450.643 (± 3.1%) i/s    (2.22 ms/i) -      2.295k in   5.098150s
           rapidjson    395.304 (± 1.5%) i/s    (2.53 ms/i) -      2.000k in   5.060537s

Comparison:
          json 2.8.0:      449.8 i/s
          Oj::Parser:      450.6 i/s - same-ish: difference falls within error
           rapidjson:      395.3 i/s - 1.14x  slower
                  oj:      358.6 i/s - 1.25x  slower
          json 2.7.2:      304.6 i/s - 1.48x  slower