Skip to content

Commit 6d9694e

Browse files
authored
Cache parsed object names (#675)
* Cache parsed object names Looking up the fstring table isn't that cheap, if we assume most object names are likely to re-appear, it makes sense to keep a small cache of them on the stack. e.g. `[{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}]` In term of implementation, we use a simple sorted array with binary search as it's the most compact and guarantee a decent `O(log n)`, and the comparison is first done on the string length, an then fallback to `memcmp`. Compactness is important here because we're allocating on the stack. There is also some simple heuristic to avoid caching names that aren't likely to be repeated, such as numerical names or very long names. This helps quite a bit on `activitypub`, `twitter` and `ctim_catalog` macro-benchmarks. Before: ``` == Parsing activitypub.json (58160 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 714.000 i/100ms oj 801.000 i/100ms Oj::Parser 943.000 i/100ms rapidjson 632.000 i/100ms Calculating ------------------------------------- json 7.135k (± 0.7%) i/s (140.16 μs/i) - 35.700k in 5.003978s oj 7.991k (± 0.2%) i/s (125.14 μs/i) - 40.050k in 5.012044s Oj::Parser 9.611k (± 0.2%) i/s (104.04 μs/i) - 48.093k in 5.003723s rapidjson 6.318k (± 0.2%) i/s (158.29 μs/i) - 31.600k in 5.001896s Comparison: json: 7134.7 i/s Oj::Parser: 9611.5 i/s - 1.35x faster oj: 7990.8 i/s - 1.12x faster rapidjson: 6317.6 i/s - 1.13x slower == Parsing twitter.json (567916 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 57.000 i/100ms oj 62.000 i/100ms Oj::Parser 78.000 i/100ms rapidjson 56.000 i/100ms Calculating ------------------------------------- json 573.527 (± 1.6%) i/s (1.74 ms/i) - 2.907k in 5.070094s oj 619.368 (± 1.6%) i/s (1.61 ms/i) - 3.100k in 5.006550s Oj::Parser 770.095 (± 0.9%) i/s (1.30 ms/i) - 3.900k in 5.064768s rapidjson 560.601 (± 0.4%) i/s (1.78 ms/i) - 2.856k in 5.094597s Comparison: json: 573.5 i/s Oj::Parser: 770.1 i/s - 1.34x faster oj: 619.4 i/s - 1.08x faster rapidjson: 560.6 i/s - 1.02x slower == Parsing citm_catalog.json (1727030 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 31.000 i/100ms oj 34.000 i/100ms Oj::Parser 46.000 i/100ms rapidjson 38.000 i/100ms Calculating ------------------------------------- json 319.842 (± 0.3%) i/s (3.13 ms/i) - 1.612k in 5.040026s oj 329.315 (± 2.4%) i/s (3.04 ms/i) - 1.666k in 5.061887s Oj::Parser 452.725 (± 1.1%) i/s (2.21 ms/i) - 2.300k in 5.080996s rapidjson 358.160 (± 0.8%) i/s (2.79 ms/i) - 1.824k in 5.093054s Comparison: json: 319.8 i/s Oj::Parser: 452.7 i/s - 1.42x faster rapidjson: 358.2 i/s - 1.12x faster oj: 329.3 i/s - 1.03x faster ``` After: ``` == Parsing activitypub.json (58160 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 832.000 i/100ms oj 799.000 i/100ms Oj::Parser 969.000 i/100ms rapidjson 636.000 i/100ms Calculating ------------------------------------- json 8.020k (± 0.3%) i/s (124.70 μs/i) - 40.768k in 5.083607s oj 7.942k (± 1.7%) i/s (125.92 μs/i) - 39.950k in 5.031909s Oj::Parser 9.515k (± 4.4%) i/s (105.10 μs/i) - 47.481k in 5.001202s rapidjson 6.282k (± 2.1%) i/s (159.20 μs/i) - 31.800k in 5.064719s Comparison: json: 8019.6 i/s Oj::Parser: 9514.5 i/s - 1.19x faster oj: 7941.9 i/s - same-ish: difference falls within error rapidjson: 6281.6 i/s - 1.28x slower == Parsing twitter.json (567916 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 67.000 i/100ms oj 62.000 i/100ms Oj::Parser 79.000 i/100ms rapidjson 55.000 i/100ms Calculating ------------------------------------- json 670.935 (± 2.7%) i/s (1.49 ms/i) - 3.417k in 5.096850s oj 618.937 (± 3.2%) i/s (1.62 ms/i) - 3.100k in 5.014800s Oj::Parser 768.894 (± 1.7%) i/s (1.30 ms/i) - 3.871k in 5.036093s rapidjson 556.882 (± 2.7%) i/s (1.80 ms/i) - 2.805k in 5.040970s Comparison: json: 670.9 i/s Oj::Parser: 768.9 i/s - 1.15x faster oj: 618.9 i/s - 1.08x slower rapidjson: 556.9 i/s - 1.20x slower == Parsing citm_catalog.json (1727030 bytes) ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23] Warming up -------------------------------------- json 35.000 i/100ms oj 32.000 i/100ms Oj::Parser 43.000 i/100ms rapidjson 39.000 i/100ms Calculating ------------------------------------- json 382.262 (± 2.6%) i/s (2.62 ms/i) - 1.925k in 5.039336s oj 348.721 (± 0.6%) i/s (2.87 ms/i) - 1.760k in 5.047265s Oj::Parser 478.294 (± 0.6%) i/s (2.09 ms/i) - 2.408k in 5.034798s rapidjson 398.740 (± 0.8%) i/s (2.51 ms/i) - 2.028k in 5.086365s Comparison: json: 382.3 i/s Oj::Parser: 478.3 i/s - 1.25x faster rapidjson: 398.7 i/s - 1.04x faster oj: 348.7 i/s - 1.10x slower ```
1 parent 217017e commit 6d9694e

File tree

3 files changed

+448
-116
lines changed

3 files changed

+448
-116
lines changed

0 commit comments

Comments
 (0)