Age | Commit message (Collapse) | Author |
|
(https://github.com/ruby/json/pull/743)
See the pull request for the long development history: https://github.com/ruby/json/pull/743
```
== Encoding activitypub.json (52595 bytes)
ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 2.913k i/100ms
Calculating -------------------------------------
after 29.377k (± 2.0%) i/s (34.04 μs/i) - 148.563k in 5.059169s
Comparison:
before: 23314.1 i/s
after: 29377.3 i/s - 1.26x faster
== Encoding citm_catalog.json (500298 bytes)
ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 152.000 i/100ms
Calculating -------------------------------------
after 1.569k (± 0.8%) i/s (637.49 μs/i) - 7.904k in 5.039001s
Comparison:
before: 1485.6 i/s
after: 1568.7 i/s - 1.06x faster
== Encoding twitter.json (466906 bytes)
ruby 3.4.2 (2025-02-15 revision https://github.com/ruby/json/commit/d2930f8e7a) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
after 309.000 i/100ms
Calculating -------------------------------------
after 3.115k (± 3.1%) i/s (321.01 μs/i) - 15.759k in 5.063776s
Comparison:
before: 2508.3 i/s
after: 3115.2 i/s - 1.24x faster
```
https://github.com/ruby/json/commit/49003523da
|
|
We can't directly call `RBASIC_CLASS` as the return value of
`to_s` may be an immediate.
https://github.com/ruby/json/commit/12dc394d11
|
|
Fix: https://github.com/ruby/json/issues/790
If we end up calling something that spills the state
on the heap, the pointer we received is outdated and
may be out of sync.
https://github.com/ruby/json/commit/2ffa4ea46b
|
|
Fix: https://github.com/ruby/json/pull/781
Tests are ran a bit differently in ruby/ruby
and this assertion breaks.
https://github.com/ruby/json/commit/0d4fc669ed
|
|
This reverts commit 09b94688731a73a4ee63969a22ba7d537223e02a.
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
https://github.com/ruby/json/commit/1b16a82980
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
By leveraging the `on_load` callback we can move all this logic
out of the parser. Which mean we no longer have to duplicate
that logic in both parser and that we'll later be able to extract
it entirely from the gem.
https://github.com/ruby/json/commit/f411ddf1ce
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
And substitute the return value like `Marshal.load` doesm
which I can only assume was the intent.
This also open the door to re-implement all the `create_addition`
logic in `json/common.rb`.
https://github.com/ruby/json/commit/73d2137fd3
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
https://github.com/ruby/json/commit/1ca7efed1f
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
https://github.com/ruby/json/commit/01c47a0555
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
https://github.com/ruby/json/commit/6508455d82
Notes:
Merged: https://github.com/ruby/ruby/pull/13004
|
|
|
|
This commit provides an alternative implementation for a
long → decimal conversion.
The main difference is that it uses an algorithm pulled from
https://github.com/jeaiii/itoa.
The source there is C++, it was converted by hand to C for
inclusion with this gem.
jeaiii's algorithm is covered by the MIT License, see source code.
On addition this version now also generates the string directly into
the fbuffer, foregoing the need to run a separate memory copy.
As a result, I see a speedup of 32% on Apple Silicon M1 for an
integer set of benchmarks.
|
|
Globally changing the behavior of the library is a bad idea, as
many different libraries may rely on `json` and may not expect it
and likely never tested that a different default config works for them.
If you need to change the behavior of JSON, it's best to do it only
locally, and not globally.
In addition the new `JSON::Coder` interface is much more suited for
that.
Another reason for the deprecation is that it's impossible to
make `JSON.load` and `JSON.dump` Ractor-safe with such API.
https://github.com/ruby/json/commit/172762c6e4
|
|
Adds a test case
fix
https://github.com/ruby/json/commit/fa5bdf87cb
|
|
This was the behavior until `2.10.0` unadvertently changed it.
`"\u1"` would raise, but `"\u1zzz"` wouldn't.
https://github.com/ruby/json/commit/7d0637b9e6
|
|
https://github.com/ruby/json/commit/2e015ff839
|
|
Fix: https://github.com/ruby/json/issues/755
Error messages now include a snippet of the document
that doesn't parse to help locate the issue, however
the way it was done wasn't UTF-8 aware, and it could
result in exception messages with truncated characters.
It would be nice to go a bit farther and actually support
codepoints, but it's a lot of complexity to do it in C,
perhaps if we move that logic to Ruby given it's not a
performance sensitive codepath.
https://github.com/ruby/json/commit/e144793b72
|
|
Fix: https://github.com/ruby/json/issues/748
`MultiJson` pass `State#to_h` as options, and the `as_json`
property defaults to `false` but `false` wasn't accepted by
the constructor.
|
|
Co-authored-by: Jean Boussier <[email protected]>
|
|
Co-authored-by: Jean Boussier <[email protected]>
|
|
The goal is to be able to dispatch to more optimized search implementations
without having to duplicate the escaping code.
Somehow, this is a few % faster already:
```
== Encoding activitypub.json (52595 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
after 2.257k i/100ms
Calculating -------------------------------------
after 22.930k (± 1.3%) i/s (43.61 μs/i) - 115.107k in 5.020814s
Comparison:
before: 21604.0 i/s
after: 22930.1 i/s - 1.06x faster
== Encoding citm_catalog.json (500298 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
after 137.000 i/100ms
Calculating -------------------------------------
after 1.397k (± 1.1%) i/s (715.57 μs/i) - 6.987k in 5.000408s
Comparison:
before: 1344.4 i/s
after: 1397.5 i/s - 1.04x faster
== Encoding twitter.json (466906 bytes)
ruby 3.4.1 (2024-12-25 revision https://github.com/ruby/json/commit/48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
after 249.000 i/100ms
Calculating -------------------------------------
after 2.464k (± 1.8%) i/s (405.81 μs/i) - 12.450k in 5.054131s
Comparison:
before: 2326.5 i/s
after: 2464.2 i/s - 1.06x faster
```
https://github.com/ruby/json/commit/8fb5ae807f
|
|
|
|
Co-authored-by: Jean Boussier <[email protected]>
|
|
https://github.com/ruby/json/commit/b9bfeecfa9
Notes:
Merged: https://github.com/ruby/ruby/pull/12602
|
|
https://github.com/ruby/json/commit/2f57f40467
Notes:
Merged: https://github.com/ruby/ruby/pull/12602
|
|
https://github.com/ruby/json/commit/86c0d4eb7e
Notes:
Merged: https://github.com/ruby/ruby/pull/12602
|
|
https://github.com/ruby/json/commit/9e3500f345
Co-authored-by: Jean Boussier <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/12602
|
|
Ref: https://github.com/ruby/ruby/pull/12598
This could lead to an infinite loop.
https://github.com/ruby/json/commit/f8cfa2696a
Notes:
Merged: https://github.com/ruby/ruby/pull/12600
|
|
And get rid of the Ragel parser.
This is 7% faster on activitypub, 15% after on twitter and 11% faster
on citm_catalog.
There might be some more optimization opportunities, I did a quick
optimization pass to fix a regression in string parsing, but other
than that I haven't dug much in performance.
Notes:
Merged: https://github.com/ruby/ruby/pull/12598
|
|
https://github.com/ruby/json/commit/c69963fbe5
|
|
Ref: https://github.com/ruby/json/pull/718
The existing `Parser` interface is pretty bad, as it forces to
instantiate a new instance for each document.
Instead it's preferable to only take the config and do all the
initialization needed, and then keep the parsing state on the
stack on in ephemeral memory.
This refactor makes the `JSON::Coder` pull request much easier to
implement in a performant way.
https://github.com/ruby/json/commit/c8d5236a92
Co-Authored-By: Étienne Barrié <[email protected]>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12531
|
|
Fix: https://github.com/ruby/json/issues/715
The first byte check was missing.
https://github.com/ruby/json/commit/93a7f8717d
Notes:
Merged: https://github.com/ruby/ruby/pull/12267
|
|
Fix: https://github.com/ruby/json/issues/710
Makes it easier to debug why a given tree of objects can't
be dumped as JSON.
Co-Authored-By: Étienne Barrié <[email protected]>
|
|
Ref: https://github.com/ruby/json/issues/524
Rather than to buffer everything in memory.
Unfortunately Ruby doesn't provide an API to write into
and IO without first allocating a string, which is a bit
wasteful.
https://github.com/ruby/json/commit/f017af6c0a
|
|
Manually sync this commit that was missed.
https://github.com/ruby/json/commit/6ae9155
|
|
Fix: https://github.com/ruby/json/issues/697
This way even if `Encoding.default_external` is set to a weird value
the document will be parsed just fine.
https://github.com/ruby/json/commit/3a8505a8fa
|
|
https://github.com/ruby/json/commit/1acce7aceb
|
|
https://github.com/ruby/json/commit/bc2c970ce4
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
https://github.com/ruby/json/commit/e85107197b
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
https://github.com/ruby/json/commit/82d21f01c5
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
subclasses
Ref: https://github.com/ruby/json/pull/674
Ref: https://github.com/ruby/json/pull/668
The behavior on such case it quite unclear, the goal here is to
figure out whatever was the behavior on Cext version of `json 2.7.0`
and get all implementations to converge.
We can then decide to make them all behave differently if we so wish.
https://github.com/ruby/json/commit/614921dcef
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
This is somewhat dead code as unless you are using `JSON::Parser.new`
direcltly we never allocate `JSON::Ext::Parser` anymore.
But still, we should mark all its reference in case some code out there
uses that.
Followup: #675
https://github.com/ruby/json/commit/8bf74a977b
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
Fix: https://github.com/ruby/json/issues/667
This is yet another behavior on which the various implementations
differed, but the C implementation used to call `to_json` on String
subclasses used as keys.
This was optimized out in e125072130229e54a651f7b11d7d5a782ae7fb65
but there is an Active Support test case for it, so it's best to
make all 3 implementation respect this behavior.
|
|
Because of it's Ruby 1.8 heritage, the C extension doesn't care
much about strings encoding. We should get stricter over time.
https://github.com/ruby/json/commit/42402fc13f
|
|
[Feature #19528]
Ref: https://bugs.ruby-lang.org/issues/19528
`load` is understood as the default method for serializer kind of libraries, and
the default options of `JSON.load` has caused many security vulnerabilities over the
years.
The plan is to do like YAML/Psych, deprecate these default options and direct
users toward using `JSON.unsafe_load` so at least it's obvious it should be
used against untrusted data.
|
|
Fix: https://github.com/ruby/json/issues/655
For very small documents, the biggest performance gap with alternatives is
that the API impose that we allocate the `State` object. In a real world app
this doesn't make much of a difference, but when running in a micro-benchmark
this doubles the allocations, causing twice the amount of GC runs, making us
look bad.
However, unless we have to call a `to_json` method, the `State` object isn't
visible, so with some refactoring, we can elude that allocation entirely.
Instead we allocate the State internal struct on the stack, and if we need
to call a `to_json` method, we allocate the `State` and spill the struct on
the heap.
As a result, `JSON.generate` is now as fast as re-using a `State` instance,
as long as only primitives are generated.
Before:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 598.654k i/100ms
json 400.542k i/100ms
oj 533.353k i/100ms
Calculating -------------------------------------
json (reuse) 6.371M (± 8.6%) i/s (156.96 ns/i) - 31.729M in 5.059195s
json 4.120M (± 6.6%) i/s (242.72 ns/i) - 20.828M in 5.090549s
oj 5.622M (± 6.4%) i/s (177.86 ns/i) - 28.268M in 5.061473s
Comparison:
json (reuse): 6371126.6 i/s
oj: 5622452.0 i/s - same-ish: difference falls within error
json: 4119991.1 i/s - 1.55x slower
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 248.125k i/100ms
json 215.255k i/100ms
oj 217.531k i/100ms
Calculating -------------------------------------
json (reuse) 2.628M (± 6.1%) i/s (380.55 ns/i) - 13.151M in 5.030281s
json 2.185M (± 6.7%) i/s (457.74 ns/i) - 10.978M in 5.057655s
oj 2.217M (± 6.7%) i/s (451.10 ns/i) - 11.094M in 5.044844s
Comparison:
json (reuse): 2627799.4 i/s
oj: 2216824.8 i/s - 1.19x slower
json: 2184669.5 i/s - 1.20x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 641.334k i/100ms
json 322.745k i/100ms
oj 642.450k i/100ms
Calculating -------------------------------------
json (reuse) 7.133M (± 6.5%) i/s (140.19 ns/i) - 35.915M in 5.068201s
json 4.615M (± 7.0%) i/s (216.70 ns/i) - 22.915M in 5.003718s
oj 6.912M (± 6.4%) i/s (144.68 ns/i) - 34.692M in 5.047690s
Comparison:
json (reuse): 7133123.3 i/s
oj: 6911977.1 i/s - same-ish: difference falls within error
json: 4614696.6 i/s - 1.55x slower
```
After:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 572.751k i/100ms
json 457.741k i/100ms
oj 512.247k i/100ms
Calculating -------------------------------------
json (reuse) 6.324M (± 6.9%) i/s (158.12 ns/i) - 31.501M in 5.023093s
json 6.263M (± 6.9%) i/s (159.66 ns/i) - 31.126M in 5.017086s
oj 5.569M (± 6.6%) i/s (179.56 ns/i) - 27.661M in 5.003739s
Comparison:
json (reuse): 6324183.5 i/s
json: 6263204.9 i/s - same-ish: difference falls within error
oj: 5569049.2 i/s - same-ish: difference falls within error
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 258.505k i/100ms
json 242.335k i/100ms
oj 220.678k i/100ms
Calculating -------------------------------------
json (reuse) 2.589M (± 9.6%) i/s (386.17 ns/i) - 12.925M in 5.071853s
json 2.594M (± 6.6%) i/s (385.46 ns/i) - 13.086M in 5.083035s
oj 2.250M (± 2.3%) i/s (444.43 ns/i) - 11.255M in 5.004707s
Comparison:
json (reuse): 2589499.6 i/s
json: 2594321.0 i/s - same-ish: difference falls within error
oj: 2250064.0 i/s - 1.15x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 656.373k i/100ms
json 644.135k i/100ms
oj 650.283k i/100ms
Calculating -------------------------------------
json (reuse) 7.202M (± 7.1%) i/s (138.84 ns/i) - 36.101M in 5.051438s
json 7.278M (± 1.7%) i/s (137.40 ns/i) - 36.716M in 5.046300s
oj 7.036M (± 1.7%) i/s (142.12 ns/i) - 35.766M in 5.084729s
Comparison:
json (reuse): 7202447.9 i/s
json: 7277883.0 i/s - same-ish: difference falls within error
oj: 7036115.2 i/s - same-ish: difference falls within error
```
|