-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Nicky Out
committed
Sep 15, 2017
1 parent
c9bb91b
commit 2a7d369
Showing
2 changed files
with
46 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,9 @@ | |
|
||
_The test only succeeds when mine is faster than substack's in a particular browser._ | ||
|
||
The most popular repository providing this feature is [substack's json-stable-stringify][sub]. The intent if this library is to provide a faster alternative for when performance is more important than features. It assumes you provide basic javascript values without circular references, and returns a non-indented string. It currently offers a performance boost in popular browsers of about 50%. Less so for modern desktop browsers (30%), more so for modern (mobile) safari (100%). For most legacy browsers, about 75%. | ||
The most popular repository providing this feature is [substack's json-stable-stringify][sub]. The intent if this library is to provide a faster alternative for when performance is more important than features. It assumes you provide basic javascript values without circular references, and returns a non-indented string. | ||
|
||
It currently offers a performance boost in popular browsers of about 40%. See the comparsion table below. | ||
|
||
Usage: | ||
|
||
|
@@ -17,91 +19,63 @@ stringify({ d: 0, c: 1, a: 2, b: 3, e: 4 }); // '{"a":2,"b":3,"c":1,"d":0,"e":4} | |
|
||
Just like substack's, it does: | ||
|
||
* handle all variations of all basic javascript values (number, string, boolean, array, object, null) | ||
* handle undefined in the same way as `JSON.stringify` | ||
* work without native access to `JSON.stringify` | ||
* **not support ie8 (and below) with complete certainty**. At least, his build failed on ie8. | ||
* handle all variations of all basic javascript values (number, string, boolean, array, object, null, Date) | ||
* handle undefined _and_ function in the same way as `JSON.stringify` | ||
* **not support ie8 (and below) with complete certainty**. | ||
|
||
Unlike substack's, it does: | ||
|
||
* not implement the 'replacer' or 'space' arguments of the JSON.stringify method | ||
* not check for circular references | ||
* not check for .toJSON() methods on objects | ||
|
||
**Upgrade warning (0.1.1 to 0.2.0):** | ||
|
||
Version 0.1.1 would sometimes return invalid JSON strings when given object properties with the value `undefined`. The response was still consistent and unique given the other properties, so I suspect in most cases this should have caused no problems. However, **if your own project is storing the results of this library (0.1.1), do note that the results will be slightly different starting with 0.2.0**. | ||
|
||
## Test results | ||
Tested validity (answer equal to substack's) and benchmark (faster than substack's). A test passes only if it has the same output as substack's but is faster (as concluded by [benchmark.js][ben]). | ||
|
||
To (hopefully) prevent [certain smart browsers][cat] from concluding the stringification is not necessary because it is never used anywhere, I summed up all the lengths of the resulting strings of each benchmark contestant and printed it along with the result data. | ||
|
||
### Latest (interpreted) result | ||
|
||
Benchmark commit 14ad70c5e1|nickyout/fast-stable-stringify|substack/json-stable-stringify|last time* |fastest* | ||
---------------------------|------------------------------|------------------------------|-----------|----------- | ||
safari 5 on Windows 2008 | x 4,317 ops/sec | x 1,534 ops/sec |+162% |+181% | ||
safari 10 on Mac 10.12 | x 6,830 ops/sec | x 3,430 ops/sec | |+99% | ||
opera 12 on Windows 2003 | x 3,084 ops/sec | x 1,938 ops/sec |+66% |+59% | ||
microsoftedge 14 on Windows| x 5,717 ops/sec | x 4,513 ops/sec | |+26% | ||
iphone 9.2 on Mac 10.10 | x 6,643 ops/sec | x 3,829 ops/sec | |+73% | ||
ipad 9.2 on Mac 10.10 | x 8,563 ops/sec | x 3,374 ops/sec | |+153% | ||
internet explorer 9 on Wind| x 6,236 ops/sec | x 2,954 ops/sec |+97% |+111% | ||
internet explorer 11 on Win| x 5,236 ops/sec | x 3,729 ops/sec |+34% |+40% | ||
internet explorer 10 on Win| x 7,520 ops/sec | x 3,435 ops/sec |+119% |+118% | ||
firefox 20 on Windows 10 | x 4,263 ops/sec | x 2,038 ops/sec |+108% |+109% | ||
chrome 57 on Windows 2008 | x 9,116 ops/sec | x 7,191 ops/sec | |+26% | ||
chrome 26 on Windows 10 | x 5,696 ops/sec | x 3,314 ops/sec |+47% |+71% | ||
android 6.0 on Linux | x 6,199 ops/sec | x 4,775 ops/sec | |+29% | ||
|
||
\* I did (nickyout / substack) - 1 in percentages | ||
|
||
Arguably faster than last time, but more importantly, most latest versions of the most popular browsers get a bump in speed. I'll call that a win. | ||
### Latest interpreted result | ||
|
||
See [caniuse browser usage][usg] for the 'most popular browsers'. | ||
|
||
| Suite | Browser | JSON.stringify@native | fast-stable-stringify@a9f81e8 | [email protected] | [email protected] | | ||
| :---- | :-------------------------------------- | --------------------: | ----------------------------: | --------------------------: | ----------------------------: | | ||
| libs | Chrome 60.0.3112 (Windows 7 0.0.0) | 414.45% (±2.67%) | *146.41% (±1.74%) | 100.00% (±1.11%) | 111.26% (±1.24%) | | ||
| libs | Chrome Mobile 55.0.2883 (Android 6.0.0) | 495.16% (±16.9%) | *162.18% (±3.59%) | 100.00% (±5.44%) | 129.66% (±3.20%) | | ||
| libs | Edge 14.14393.0 (Windows 10 0.0.0) | 487.88% (±11.9%) | *138.69% (±2.27%) | 100.00% (±1.51%) | 113.19% (±1.56%) | | ||
| libs | Firefox 54.0.0 (Windows 7 0.0.0) | 530.66% (±17.6%) | *169.34% (±2.38%) | 100.00% (±1.68%) | 152.30% (±2.48%) | | ||
| libs | IE 10.0.0 (Windows 7 0.0.0) | 427.80% (±10.9%) | *183.26% (±3.02%) | 100.00% (±2.42%) | ? | | ||
| libs | IE 11.0.0 (Windows 7 0.0.0) | 298.01% (±4.35%) | *136.25% (±1.89%) | 100.00% (±1.73%) | ? | | ||
| libs | IE 9.0.0 (Windows 7 0.0.0) | 316.18% (±4.01%) | *170.14% (±2.30%) | 100.00% (±1.52%) | ? | | ||
| libs | Mobile Safari 10.0.0 (iOS 10.3.0) | 554.98% (±23.7%) | *115.33% (±4.23%) | 100.00% (±3.11%) | *118.66% (±2.96%) | | ||
| libs | Safari 10.0.1 (Mac OS X 10.12.1) | 722.94% (±24.8%) | *119.49% (±3.62%) | 100.00% (±2.12%) | 106.06% (±3.12%) | | ||
|
||
Click the build status badge to view the original output. | ||
|
||
## Also | ||
It exposes the way strings are escaped for JSON: | ||
Disclaimer: the more I test the more I realize how many factors actually affect the outcome. Not only the browser and browser version, but particularly the json content and a random factor in every test run. Outcomes may sometimes vary more than 10% between tests, despite my attempt to reduce this by increasing the sample size to 2.5 times. Nevertheless, the overall picture typically still holds. | ||
|
||
```javascript | ||
var stringify = require('./'), | ||
stringSearch = stringify.stringSearch, | ||
stringReplace = stringify.stringReplace, | ||
str = "ay\nb0ss"; | ||
str.replace(stringSearch, stringReplace); // 'ay\\nb0ss' | ||
``` | ||
`JSON.stringify` has been added for reference. In general, aside from the cases where you need the guarantee of a stable result, I would recommend against using this library, or any stable stringification library for that matter. | ||
|
||
It does NOT add the quotes before and after the string needed for JSON.stringify-ing strings. Fortunately, that isn't hard: | ||
[`faster-stable-stringify`][fss] has been added for comparison. It seems it does not work in IE 9 to 11 without a polyfill solution for WeakMap. It is displayed as somewhat slower, but as I decided on the JSON input to test and develop against, this result may be somewhat biased. In some test runs, [`faster-stable-stringify`][fss] will be faster in a browser. In fact, it is consistently somewhat faster in the Mobile Safari 10. | ||
|
||
```javascript | ||
'"' + str.replace(stringSearch, stringReplace) + '"'; // '"ay\\nb0ss"' | ||
``` | ||
## Note about string escaping | ||
The original implementation was with regexp. A pull request showed a literal string approach that was faster in some browsers. Other libraries would just use JSON.stringify. After a speed comparison between all three methods, it became clear that native JSON.stringify is generally much faster in string escaping than both these methods, even in the IE legacy browsers. The browsers that do not have `JSON.stringify` are not offered for test automation, and when looking at the [usage percentage][usg] of such browsers I no longer see a reason to not use `JSON.stringify`. | ||
|
||
Therefore, the exposed regexp and string are removed from the API. If you still need this functionality, I simply encourage you to use `JSON.stringify`. | ||
|
||
## Running tests | ||
For testing in node, do: | ||
It runs karma-benchmark tests now. For testing in node, do: | ||
|
||
``` | ||
npm test | ||
``` | ||
|
||
I used [zuul][zul] for testing on saucelabs. It's a very easy to use tool, but because their library is about 150MB I did not include it in the devDepencencies. I suggest installing it globally if you want to test: | ||
|
||
``` | ||
# install zuul | ||
npm install -g zuul | ||
# then, to run all tests | ||
zuul -- test/index.js | ||
``` | ||
|
||
## TODO | ||
This requires [saucelabs credentials in your env][env]. That, or edit the karma.conf.js to your liking. | ||
|
||
* Test more unicode chars | ||
Running this test will cause files in `./results/libs/` to update. Run `npm run table` to get a pretty md table of the results. | ||
|
||
[sub]: https://github.com/substack/json-stable-stringify | ||
[ben]: https://github.com/bestiejs/benchmark.js | ||
[cat]: http://mrale.ph/blog/2014/02/23/the-black-cat-of-microbenchmarks.html | ||
[usg]: http://caniuse.com/usage-table | ||
[zul]: https://github.com/defunctzombie/zuul | ||
[env]: https://wiki.saucelabs.com/display/DOCS/Best+Practice%3A+Use+Environment+Variables+for+Authentication+Credentials | ||
[fss]: https://github.com/ppaskaris/faster-stable-stringify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,15 @@ | ||
| Suite | Browser | fast-stable-stringify@48915d2 | [email protected] | JSON.stringify@native | [email protected] | | ||
| :---- | :-------------------------------------- | ----------------------------: | --------------------------: | --------------------: | ----------------------------: | | ||
| libs | Chrome 60.0.3112 (Windows 7 0.0.0) | *100.00% (±1.14%) | 68.95% (±0.77%) | 277.33% (±3.72%) | 76.57% (±1.02%) | | ||
| libs | Chrome Mobile 55.0.2883 (Android 6.0.0) | *100.00% (±3.93%) | 70.42% (±1.60%) | 354.05% (±9.20%) | *99.42% (±4.30%) | | ||
| libs | Edge 14.14393.0 (Windows 10 0.0.0) | *100.00% (±1.31%) | 74.90% (±1.19%) | 337.28% (±7.85%) | 80.22% (±1.34%) | | ||
| libs | Firefox 54.0.0 (Windows 7 0.0.0) | *100.00% (±1.87%) | 60.66% (±1.29%) | 299.97% (±12.9%) | 94.43% (±1.63%) | | ||
| libs | IE 10.0.0 (Windows 7 0.0.0) | *100.00% (±2.10%) | 45.89% (±0.56%) | 225.65% (±6.11%) | ? | | ||
| libs | IE 11.0.0 (Windows 7 0.0.0) | *100.00% (±2.58%) | 72.23% (±1.53%) | 230.48% (±5.32%) | ? | | ||
| libs | IE 9.0.0 (Windows 7 0.0.0) | *100.00% (±0.95%) | 57.29% (±0.90%) | 157.86% (±3.43%) | ? | | ||
| libs | Mobile Safari 10.0.0 (iOS 10.3.0) | *100.00% (±3.51%) | 63.71% (±2.11%) | 424.94% (±17.1%) | 70.74% (±2.40%) | | ||
| libs | Safari 10.0.1 (Mac OS X 10.12.1) | *100.00% (±3.86%) | 79.84% (±1.49%) | 577.41% (±9.97%) | 74.71% (±3.05%) | | ||
|
||
> [email protected] table /var/www/fast-stable-stringify | ||
> node ./cli/index.js results/libs/*.json | ||
| Suite | Browser | JSON.stringify@native | fast-stable-stringify@48915d2 | [email protected] | [email protected] | | ||
| :---- | :-------------------------------------- | --------------------: | ----------------------------: | --------------------------: | ----------------------------: | | ||
| libs | Chrome 60.0.3112 (Windows 7 0.0.0) | 401.69% (±8.33%) | *154.24% (±2.21%) | 100.00% (±2.08%) | 112.80% (±2.43%) | | ||
| libs | Chrome Mobile 55.0.2883 (Android 6.0.0) | 442.96% (±24.6%) | *149.99% (±3.69%) | 100.00% (±4.11%) | 127.49% (±2.23%) | | ||
| libs | Edge 14.14393.0 (Windows 10 0.0.0) | 452.54% (±8.66%) | *131.31% (±2.46%) | 100.00% (±1.38%) | 110.88% (±1.21%) | | ||
| libs | Firefox 54.0.0 (Windows 7 0.0.0) | 486.58% (±18.1%) | *156.10% (±3.53%) | 100.00% (±3.59%) | 128.86% (±3.73%) | | ||
| libs | IE 10.0.0 (Windows 7 0.0.0) | 419.75% (±13.8%) | *199.75% (±5.28%) | 100.00% (±1.91%) | ? | | ||
| libs | IE 11.0.0 (Windows 7 0.0.0) | 314.45% (±5.07%) | *139.88% (±1.89%) | 100.00% (±1.14%) | ? | | ||
| libs | IE 9.0.0 (Windows 7 0.0.0) | 317.90% (±3.63%) | *185.72% (±1.37%) | 100.00% (±1.62%) | ? | | ||
| libs | Mobile Safari 10.0.0 (iOS 10.3.0) | 746.20% (±14.7%) | *128.14% (±2.21%) | 100.00% (±1.52%) | *123.21% (±3.26%) | | ||
| libs | Safari 10.0.1 (Mac OS X 10.12.1) | 765.32% (±15.0%) | *125.73% (±2.62%) | 100.00% (±1.39%) | 106.87% (±2.29%) | |