summaryrefslogtreecommitdiff
path: root/ext/json
AgeCommit message (Collapse)Author
2024-10-26[ruby/json] Workaround rubygems $LOAD_PATH bugJean Boussier
Ref: https://github.com/ruby/json/issues/647 Ref: https://github.com/rubygems/rubygems/pull/6490 Older rubygems are executing `extconf.rb` with a broken `$LOAD_PATH` causing the `json` gem native extension to be loaded with the stdlib version of the `.rb` files. This fails with ``` json/common.rb:82:in `initialize': wrong number of arguments (given 1, expected 0) (ArgumentError) ``` Since this is just for `extconf.rb` we can probably just accept that extra argument and ignore it. The bug was fixed in rubygems 3.4.9 / 2023-03-20 https://github.com/ruby/json/commit/1f5e849fe0
2024-10-26[ruby/json] Use smaller types for JSON_Parser boolean fieldsJean Boussier
https://github.com/ruby/json/commit/7f079b25be
2024-10-26[ruby/json] Modernize heredocsJean Boussier
https://github.com/ruby/json/commit/fb25e94aea
2024-10-26pretty_generate: don't apply object_nl / array_nl for empty containersJean Boussier
Fix: https://github.com/ruby/json/issues/437 Before: ```json { "foo": { }, "bar": [ ] } ``` After: ```json { "foo": {}, "bar": [] } ```
2024-10-26Set Ruby 2.7 as the required versionJean Boussier
2024-10-26[ruby/json] Start 2.8.0 developmentJean Boussier
https://github.com/ruby/json/commit/937c8d2e65
2024-10-26[ruby/json] Release 2.7.3Jean Boussier
https://github.com/ruby/json/commit/7a3b482013
2024-10-26[ruby/json] Release 2.7.3.rc1Jean Boussier
https://github.com/ruby/json/commit/a48be35825
2024-10-26Merge json and json-java gemspecsJean Boussier
2024-10-26[ruby/json] JSON.dump / String#to_json: raise on invalid encodingJean Boussier
This regressed since 2.7.2. https://github.com/ruby/json/commit/35407d6635
2024-10-26[ruby/json] Add lib/json/ext/generator/state.rb to the gemspecBenoit Daloze
* Otherwise the gem always uses the pure-Ruby backend as it's missing that file and rescuing the LoadError. https://github.com/ruby/json/commit/1e2809b0b0
2024-10-26[ruby/json] raise_parse_error: avoid UBJean Boussier
Fix: https://github.com/ruby/json/pull/625 Declaring the buffer in a sub block cause bugs on some compilers. https://github.com/ruby/json/commit/90967c9eb0
2024-10-26Use frozen string literalsÉtienne Barrié
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-10-26[ruby/json] Drop compatibility for missing Time#tv_nsec (Ruby 1.8)Étienne Barrié
https://github.com/ruby/json/commit/b240bde402 Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-10-26[ruby/json] Compile with std=c99Jean Boussier
https://github.com/ruby/json/commit/d4968d2e48
2024-10-26[ruby/json] convert_UTF8_to_ASCII_only_JSON: apply the same optimization passJean Boussier
https://github.com/ruby/json/commit/42edaf7f17
2024-10-26[ruby/json] Reduce encoding benchmark sizeJean Boussier
Profiling revealed that we were spending lots of time growing the buffer. Buffer operations is definitely something we want to optimize, but for this specific benchmark what we're interested in is UTF-8 scanning performance. Each iteration of the two scaning benchmark were producing 20MB of JSON, now they only produce 5MB. Now: ``` == Encoding mostly utf8 (5001001 bytes) ruby 3.4.0dev (2024-10-18T19:01:45Z master https://github.com/ruby/json/commit/7be9a333ca) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 35.000 i/100ms oj 36.000 i/100ms rapidjson 10.000 i/100ms Calculating ------------------------------------- json 359.161 (± 1.4%) i/s (2.78 ms/i) - 1.820k in 5.068542s oj 359.699 (± 0.6%) i/s (2.78 ms/i) - 1.800k in 5.004291s rapidjson 99.687 (± 2.0%) i/s (10.03 ms/i) - 500.000 in 5.017321s Comparison: json: 359.2 i/s oj: 359.7 i/s - same-ish: difference falls within error rapidjson: 99.7 i/s - 3.60x slower ``` https://github.com/ruby/json/commit/1a338532d2
2024-10-26[ruby/json] convert_UTF8_to_JSON: repurpose the escape tables into size tablesJean Boussier
Since we're looking up the table anyway, we might as well store the UTF-8 char length in it. For single byte characters that don't need escaping we store `0`. This helps on strings with lots of multi-byte characters: Before: ``` == Encoding mostly utf8 (20004001 bytes) ruby 3.3.4 (2024-07-09 revision https://github.com/ruby/json/commit/be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 6.000 i/100ms oj 10.000 i/100ms rapidjson 2.000 i/100ms Calculating ------------------------------------- json 67.978 (± 1.5%) i/s (14.71 ms/i) - 342.000 in 5.033062s oj 100.876 (± 2.0%) i/s (9.91 ms/i) - 510.000 in 5.058080s rapidjson 26.389 (± 7.6%) i/s (37.89 ms/i) - 132.000 in 5.027681s Comparison: json: 68.0 i/s oj: 100.9 i/s - 1.48x faster rapidjson: 26.4 i/s - 2.58x slower ``` After: ``` == Encoding mostly utf8 (20004001 bytes) ruby 3.3.4 (2024-07-09 revision https://github.com/ruby/json/commit/be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 7.000 i/100ms oj 10.000 i/100ms rapidjson 2.000 i/100ms Calculating ------------------------------------- json 75.187 (± 2.7%) i/s (13.30 ms/i) - 378.000 in 5.030111s oj 95.196 (± 2.1%) i/s (10.50 ms/i) - 480.000 in 5.043565s rapidjson 25.969 (± 3.9%) i/s (38.51 ms/i) - 130.000 in 5.011471s Comparison: json: 75.2 i/s oj: 95.2 i/s - 1.27x faster rapidjson: 26.0 i/s - 2.90x slower ``` https://github.com/ruby/json/commit/51e2631d1f
2024-10-26[ruby/json] Optimize convert_UTF8_to_JSON for mostly ASCII stringsJean Boussier
If we assume that even UTF-8 strings are mostly ASCII, we can implement a fast path for the ASCII parts. Before: ``` == Encoding mixed utf8 (20012001 bytes) ruby 3.4.0dev (2024-10-18T15:12:54Z master https://github.com/ruby/json/commit/d1b5c10957) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 5.000 i/100ms oj 9.000 i/100ms rapidjson 2.000 i/100ms Calculating ------------------------------------- json 49.403 (± 2.0%) i/s (20.24 ms/i) - 250.000 in 5.062647s oj 100.120 (± 2.0%) i/s (9.99 ms/i) - 504.000 in 5.035349s rapidjson 26.404 (± 0.0%) i/s (37.87 ms/i) - 132.000 in 5.001025s Comparison: json: 49.4 i/s oj: 100.1 i/s - 2.03x faster rapidjson: 26.4 i/s - 1.87x slower ``` After: ``` == Encoding mixed utf8 (20012001 bytes) ruby 3.4.0dev (2024-10-18T15:12:54Z master https://github.com/ruby/json/commit/d1b5c10957) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 10.000 i/100ms oj 9.000 i/100ms rapidjson 2.000 i/100ms Calculating ------------------------------------- json 95.686 (± 2.1%) i/s (10.45 ms/i) - 480.000 in 5.018575s oj 96.875 (± 2.1%) i/s (10.32 ms/i) - 486.000 in 5.019097s rapidjson 26.260 (± 3.8%) i/s (38.08 ms/i) - 132.000 in 5.033151s Comparison: json: 95.7 i/s oj: 96.9 i/s - same-ish: difference falls within error rapidjson: 26.3 i/s - 3.64x slower ``` https://github.com/ruby/json/commit/f8166c2d7f
2024-10-26[ruby/json] Ext::Parser avoid costly check on decimal_class when it is nilJean Boussier
Closes: https://github.com/ruby/json/pull/512 https://github.com/ruby/json/commit/d882a45d82 Co-Authored-By: lukeg <luke.gru@gmail.com>
2024-10-26[ruby/json] Limit the size of ParserError exception messagesJean Boussier
Fix: https://github.com/ruby/json/issues/534 Only include up to 32 bytes of unparseable the source. https://github.com/ruby/json/commit/f44995cfb6
2024-10-26[ruby/json] parser.c: refactor raise_parse_errorJean Boussier
https://github.com/ruby/json/commit/09e1df2643
2024-10-26[ruby/json] Get rid of the remaining tabs.Jean Boussier
https://github.com/ruby/json/commit/1a9af430d2
2024-10-26Reduce allocations in `parse` and `load` argument handlingJean Boussier
Avoid needless hash allocations and such that degrade performance significantly on micro-benchmarks.
2024-10-26Add more precise documentation for `object_class` and `array_class`Jean Boussier
Fix: https://github.com/ruby/json/issues/419
2024-10-18[ruby/json] Always dup argument to preserve original encoding for force_encodingTakumasa Ochi
https://github.com/ruby/json/commit/db9a489ca2
2024-10-18[ruby/json] Fix behavior of trying to parse non-string objectsYuheiNakasaka
https://github.com/ruby/json/commit/e2e9936047
2024-10-18[ruby/json] Speedup Parser initializationJean Boussier
Extracted from: https://github.com/ruby/json/pull/512 Use `rb_hash_lookup2` to check for hash key existence instead of going through `rb_funcall`. https://github.com/ruby/json/commit/43835a0d13 Co-Authored-By: lukeg <luke.gru@gmail.com>
2024-10-17[ruby/json] Sync changesPeter Zhu
Some changes were missed in the automatic sync. Notes: Merged: https://github.com/ruby/ruby/pull/11911
2024-10-17[ruby/json] Fix State#max_nesting=Peter Zhu
Returning state->max_nesting is not valid because it's not a Ruby object. https://github.com/ruby/json/commit/6679ceb
2024-10-17Add a fast path for ASCII stringsJean Boussier
This optimization is based on a few assumptions: - Most strings are ASCII only. - Most strings had their coderange scanned already. If the above is true, then by checking the string coderange, we can use a much more streamlined function to encode ASCII strings. Before: ``` == Encoding twitter.json (466906 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 140.000 i/100ms oj 230.000 i/100ms rapidjson 108.000 i/100ms Calculating ------------------------------------- json 1.464k (± 1.4%) i/s (682.83 μs/i) - 7.420k in 5.067573s oj 2.338k (± 1.5%) i/s (427.64 μs/i) - 11.730k in 5.017336s rapidjson 1.075k (± 1.6%) i/s (930.40 μs/i) - 5.400k in 5.025469s Comparison: json: 1464.5 i/s oj: 2338.4 i/s - 1.60x faster rapidjson: 1074.8 i/s - 1.36x slower ``` After: ``` == Encoding twitter.json (466906 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 189.000 i/100ms oj 228.000 i/100ms rapidjson 108.000 i/100ms Calculating ------------------------------------- json 1.903k (± 1.2%) i/s (525.55 μs/i) - 9.639k in 5.066521s oj 2.306k (± 1.3%) i/s (433.71 μs/i) - 11.628k in 5.044096s rapidjson 1.069k (± 2.4%) i/s (935.38 μs/i) - 5.400k in 5.053794s Comparison: json: 1902.8 i/s oj: 2305.7 i/s - 1.21x faster rapidjson: 1069.1 i/s - 1.78x slower ```
2024-10-17[ruby/json] Get rid of some more outdated compatibility codeJean Boussier
All these macros are available on Ruby 2.3+ https://github.com/ruby/json/commit/227885f460
2024-10-17[ruby/json] Get rid of compatibility code for older rubiesJean Boussier
All of these are for rubies older than 2.3. https://github.com/ruby/json/commit/811297f86a
2024-10-17Optimize Ext::Generator::State#configureJean Boussier
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 ```
2024-10-17[ruby/json] generator.c: reduce the number of globalsJean Boussier
Most of these classes and modules don't need to be global variables https://github.com/ruby/json/commit/b783445ec9
2024-10-17[ruby/json] Convert Generator initialize and configure method into RubyJean Boussier
This helps very marginally with allocation speed. https://github.com/ruby/json/commit/25db79dfaa
2024-10-17Optimize JSON.dump argument parsingJean Boussier
`JSON.dump` looks terrible on micro-benchmarks because the way it handles arguments is quite allocation heavy compared to the actual JSON generation work. Profiling the `small hash` benchmarked show 14% of time spent in `Array#compact` and `34%` time spent in `JSON::Ext::GeneratorState.new`. Only `41%` in the actual `generate` function. By micro-optimizing `JSON.dump`, it can look much better: Before: ``` == Encoding small nested array (121 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 91.687k i/100ms oj 205.309k i/100ms rapidjson 161.648k i/100ms Calculating ------------------------------------- json 941.965k (± 1.4%) i/s (1.06 μs/i) - 4.768M in 5.062573s oj 2.138M (± 1.2%) i/s (467.82 ns/i) - 10.881M in 5.091254s rapidjson 1.678M (± 1.9%) i/s (596.04 ns/i) - 8.406M in 5.011931s Comparison: json: 941964.8 i/s oj: 2137586.5 i/s - 2.27x faster rapidjson: 1677737.1 i/s - 1.78x faster == Encoding small hash (65 bytes) ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23] Warming up -------------------------------------- json 141.737k i/100ms oj 676.871k i/100ms rapidjson 373.266k i/100ms Calculating ------------------------------------- json 1.491M (± 1.0%) i/s (670.78 ns/i) - 7.512M in 5.039463s oj 7.226M (± 1.4%) i/s (138.39 ns/i) - 36.551M in 5.059475s rapidjson 3.729M (± 2.2%) i/s (268.15 ns/i) - 18.663M in 5.007182s Comparison: json: 1490798.2 i/s oj: 7225766.2 i/s - 4.85x faster rapidjson: 3729192.2 i/s - 2.50x faster ``` After: ``` == 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 ``` Now profiles of the `small hash` benchmark show 44% in `generate` and `45%` in `GeneratorState` allocation.
2024-10-17[ruby/json] Use `RB_ENCODING_GET` instead of `rb_enc_get` to improve performanceYusuke Endoh
This speeds up `JSON.generate` by about 12% in a benchmark. https://github.com/ruby/json/commit/4329e30826
2024-10-17[ruby/json] Apply RB_UNLIKELY for less frequently used optionsYusuke Endoh
This speeds up `JSON.generate` by about 4% in a benchmark. https://github.com/ruby/json/commit/6471710cfc
2024-10-17[ruby/json] Stop prebuilding object_delim2Yusuke Endoh
Also, remove static functions that are no longer used. This speeds up `JSON.generate` by about 5% in a benchmark. https://github.com/ruby/json/commit/4c984b2017
2024-10-17[ruby/json] Stop prebuilding object_delimYusuke Endoh
This speeds up `JSON.generate` by about 4% in a benchmark https://github.com/ruby/json/commit/ed47a10e4f
2024-10-17[ruby/json] Stop prebuilding array_delimYusuke Endoh
The purpose of this change is to exploit `fbuffer_append_char` that is faster than `fbuffer_append`. `array_delim` was a buffer that concatenated a single comma with `array_nl`. However, in the typical use case (`JSON.generate(data)`), `array_nl` is empty. This means that `array_delim` was a single-character buffer in many cases. `fbuffer_append(buffer, array_delim)` used `memcpy` to copy one byte, which was not so efficient. Rather, this change uses `fbuffer_append_char(buffer, ',')` and then `fbuffer_append(buffer, array_nl)` only when `array_nl` is not NULL. This speeds up `JSON.generate` by about 9% in a benchmark. https://github.com/ruby/json/commit/445de6e459
2024-10-17[ruby/json] Directly use `generate_json_string` for object keysYusuke Endoh
... instead of `generate_json`. Since the object key is already confirmed to be a string, using a generic dispatch function brings an unnecessary overhead. This speeds up `JSON.generate` by about 3% in a benchmark. https://github.com/ruby/json/commit/e125072130
2024-10-17[ruby/json] Use efficient object-type dispatchingYusuke Endoh
Dispatching based on Ruby's VALUE structure is more efficient than simply cascaded "if ... else if ..." checks. This speeds up `JSON.generate` by about 5% in a benchmark. https://github.com/ruby/json/commit/4f9180debb
2024-10-17[ruby/json] Use `RARRAY_AREF` instead of `rb_ary_entry` to improve performanceYusuke Endoh
It is safe to use `RARRAY_AREF` here because no Ruby code is executed between `RARRAY_LEN` and `RARRAY_AREF`. This speeds up `JSON.generate` by about 4% in a benchmark. https://github.com/ruby/json/commit/c5d80f9fd4
2024-10-15[ruby/json] Added license files on gemspecHiroshi SHIBATA
https://github.com/ruby/json/commit/81092639e8
2024-10-15[ruby/json] Update gemspec filesJean Boussier
https://github.com/ruby/json/commit/0f9564104f
2024-10-08[ruby/json] generator.c: better fix for comparison of integers of different ↵Jean Boussier
signs https://github.com/ruby/json/commit/c372dc9268
2024-10-08Fixed C23 compilation error with ruby/ruby masterHiroshi SHIBATA
2024-10-08[ruby/json] Unicode string like § is not allowed in C files at ruby/ruby repoHiroshi SHIBATA
https://github.com/ruby/json/commit/53409bcc74