Closed BridgeAR closed 6 years ago
so... from what I can see you've reimplemented JSON.stringify
First to be clear, let me just say: awesome.
Before we can go forward though, we need to benchmark this excessively for as many scenarios as possible vs JSON.stringify
We know from past experiments that getting on par with JSON.stringify
was
pretty much impossible because of the TCO trick they use in
the native implementation – so we need to be extremely thorough in establishing this is a performance improvement across the board
What we don't want is people using fast-safe-stringify having a noticeable slow-down in their use cases
@mcollina what are your thoughts?
I understand the concerns about it. My main reason was to see how well it performs and i wanted to overcome the negative implementation parts.
I only implemented this for the stable version because the regular one is faster the way it is right now. With the added overhead in the stable version it makes sense to have this implementation though.
What we can do is to add lots of tests to make sure it works fine.
How about we do: fast-stable-stringify? I prefer small modules with a single purpose.
The original intention against it was that there are multiple out there (all with "fast" in their name...) but I will go ahead and create a new package when I am at home. We can reference to it :)
Ok, I just created https://github.com/BridgeAR/safe-stable-stringify
I fixed bugs, rewrote some more stuff and improved the performance further. Here a comparison to the current solution to the new one:
Old:
simple: simple object x 950,953 ops/sec ±1.21% (91 runs sampled)
simple: circular x 369,246 ops/sec ±0.91% (89 runs sampled)
simple: deep x 15,143 ops/sec ±1.17% (88 runs sampled)
simple: deep circular x 13,962 ops/sec ±3.04% (87 runs sampled)
replacer: simple object x 465,644 ops/sec ±1.73% (86 runs sampled)
replacer: circular x 213,329 ops/sec ±0.75% (92 runs sampled)
replacer: deep x 11,723 ops/sec ±1.56% (92 runs sampled)
replacer: deep circular x 11,364 ops/sec ±1.82% (90 runs sampled)
array: simple object x 714,791 ops/sec ±0.31% (95 runs sampled)
array: circular x 446,081 ops/sec ±1.69% (88 runs sampled)
array: deep x 25,168 ops/sec ±0.61% (93 runs sampled)
array: deep circular x 23,010 ops/sec ±3.50% (85 runs sampled)
full replacer: simple object x 395,189 ops/sec ±0.95% (91 runs sampled)
full replacer: circular x 195,702 ops/sec ±1.14% (89 runs sampled)
full replacer: deep x 9,581 ops/sec ±1.11% (91 runs sampled)
full replacer: deep circular x 9,901 ops/sec ±1.26% (93 runs sampled)
full array: simple object x 616,108 ops/sec ±0.88% (96 runs sampled)
full array: circular x 410,485 ops/sec ±1.24% (90 runs sampled)
full array: deep x 24,772 ops/sec ±1.32% (89 runs sampled)
full array: deep circular x 23,860 ops/sec ±1.80% (94 runs sampled)
indentation: simple object x 754,916 ops/sec ±1.38% (94 runs sampled)
indentation: circular x 309,293 ops/sec ±1.12% (96 runs sampled)
indentation: deep x 12,311 ops/sec ±1.46% (94 runs sampled)
indentation: deep circular x 12,174 ops/sec ±1.88% (93 runs sampled)
New
simple: simple object x 1,733,045 ops/sec ±1.82% (86 runs sampled)
simple: circular x 717,021 ops/sec ±0.78% (91 runs sampled)
simple: deep x 17,674 ops/sec ±0.77% (94 runs sampled)
simple: deep circular x 17,396 ops/sec ±0.70% (93 runs sampled)
replacer: simple object x 1,126,942 ops/sec ±2.22% (91 runs sampled)
replacer: circular x 541,243 ops/sec ±0.87% (94 runs sampled)
replacer: deep x 17,229 ops/sec ±0.90% (94 runs sampled)
replacer: deep circular x 16,948 ops/sec ±0.86% (97 runs sampled)
array: simple object x 1,470,751 ops/sec ±0.84% (95 runs sampled)
array: circular x 1,360,269 ops/sec ±2.94% (91 runs sampled)
array: deep x 1,289,785 ops/sec ±2.82% (87 runs sampled)
array: deep circular x 1,400,577 ops/sec ±1.00% (92 runs sampled)
full replacer: simple object x 993,352 ops/sec ±1.49% (92 runs sampled)
full replacer: circular x 467,264 ops/sec ±0.68% (95 runs sampled)
full replacer: deep x 14,855 ops/sec ±0.82% (91 runs sampled)
full replacer: deep circular x 14,608 ops/sec ±1.68% (95 runs sampled)
full array: simple object x 1,233,430 ops/sec ±0.58% (92 runs sampled)
full array: circular x 1,205,360 ops/sec ±1.33% (90 runs sampled)
full array: deep x 1,175,758 ops/sec ±0.63% (92 runs sampled)
full array: deep circular x 1,171,813 ops/sec ±1.08% (92 runs sampled)
indentation: simple object x 1,385,853 ops/sec ±2.18% (94 runs sampled)
indentation: circular x 598,650 ops/sec ±1.26% (92 runs sampled)
indentation: deep x 16,060 ops/sec ±0.76% (93 runs sampled)
indentation: deep circular x 15,784 ops/sec ±1.31% (95 runs sampled)
This is a performance improvement in many cases. For big / deep objects it will be a minor performance penalty in the case no options are used. If options are used (i.e. replacer or spacer) it will always be faster.
The implementation is side effect free, so it now works 1-to-1 as JSON.stringify.
For performance reasons this is a lot of duplicated code... I do not see a much nicer implementation right now that could do the same though :/.
No options:
Spacer
Replacer
Both