├── .gitignore ├── renovate.json ├── .editorconfig ├── package.json ├── index.js ├── fixture.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@ahmadnassri" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "benchmark-node-json-parse", 4 | "description": "What is the fastest method to parse JSON files?", 5 | "author": "Ahmad Nassri (https://www.ahmadnassri.com/)", 6 | "homepage": "https://github.com/ahmadnassri/benchmark-node-json-parse", 7 | "repository": "ahmadnassri/benchmark-node-json-parse", 8 | "license": "MIT", 9 | "bin": "index.js", 10 | "engines": { 11 | "node": ">= 4" 12 | }, 13 | "files": [ 14 | "index.js", 15 | "fixture.json" 16 | ], 17 | "bugs": { 18 | "url": "https://github.com/ahmadnassri/benchmark-node-json-parse/issues" 19 | }, 20 | "scripts": { 21 | "pretest": "standard && echint", 22 | "test": "node index" 23 | }, 24 | "devDependencies": { 25 | "beautify-benchmark": "^0.2.4", 26 | "benchmark": "^2.1.1", 27 | "chalk": "^1.1.3", 28 | "clarinet": "^0.11.0", 29 | "echint": "^3.0.0", 30 | "jju": "^1.3.0", 31 | "json-parse-stream": "0.0.2", 32 | "jsonparse": "^1.2.0", 33 | "stream-json": "^0.4.2", 34 | "vuvuzela": "^1.0.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // dependencies 4 | var Benchmark = require('benchmark') 5 | var benchmarks = require('beautify-benchmark') 6 | var chalk = require('chalk') 7 | var fs = require('fs') 8 | 9 | // libs 10 | var clarinet = require('clarinet') 11 | var jju = require('jju') 12 | var Jsonparse = require('jsonparse') 13 | var JsonParseStream = require('json-parse-stream') 14 | var streamJson = require('stream-json') 15 | var vuvuzela = require('vuvuzela') 16 | 17 | // test 18 | var json = fs.readFileSync('fixture.json').toString() 19 | 20 | new Benchmark.Suite() 21 | .add({ 22 | name: 'clarinet', 23 | defer: true, 24 | fn: function (deferred) { 25 | var stream = clarinet.createStream() 26 | 27 | stream.on('end', function () { 28 | deferred.resolve() 29 | }) 30 | 31 | fs.createReadStream('fixture.json').pipe(stream) 32 | } 33 | }) 34 | 35 | .add({ 36 | name: 'JSON.parse', 37 | fn: function () { 38 | JSON.parse(json) 39 | } 40 | }) 41 | 42 | .add({ 43 | name: 'jju', 44 | fn: function () { 45 | jju.parse(json) 46 | } 47 | }) 48 | 49 | .add({ 50 | name: 'jsonparse', 51 | defer: true, 52 | fn: function (deferred) { 53 | var p = new Jsonparse() 54 | p.onValue = function (data) { 55 | if (this.stack.length === 0) { 56 | deferred.resolve() 57 | } 58 | } 59 | 60 | p.write(json) 61 | } 62 | }) 63 | 64 | .add({ 65 | name: 'json-parse-stream', 66 | defer: true, 67 | fn: function (deferred) { 68 | fs.createReadStream('fixture.json') 69 | .pipe(JsonParseStream()) 70 | .on('data', function (data) { 71 | if (data.parent === undefined) { 72 | deferred.resolve() 73 | } 74 | }) 75 | } 76 | }) 77 | 78 | .add({ 79 | name: 'stream-json', 80 | defer: true, 81 | fn: function (deferred) { 82 | var source = streamJson() 83 | 84 | source.on('end', function () { 85 | deferred.resolve() 86 | }) 87 | 88 | fs.createReadStream('fixture.json').pipe(source.input) 89 | } 90 | }) 91 | 92 | .add({ 93 | name: 'vuvuzela', 94 | fn: function () { 95 | vuvuzela.parse(json) 96 | } 97 | }) 98 | 99 | // add listeners 100 | .on('cycle', function (event) { 101 | benchmarks.add(event.target) 102 | }) 103 | 104 | .on('complete', function () { 105 | benchmarks.log() 106 | 107 | console.log('Fastest is %s', chalk.green(this.filter('fastest').map('name'))) 108 | console.log('Slowest is %s', chalk.red(this.filter('slowest').map('name'))) 109 | }) 110 | 111 | .run({ 112 | 'async': true 113 | }) 114 | -------------------------------------------------------------------------------- /fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "version": "1.2", 4 | "creator": { 5 | "name": "WebInspector", 6 | "version": "537.36" 7 | }, 8 | "pages": [ 9 | { 10 | "startedDateTime": "2015-02-10T07:33:17.146Z", 11 | "id": "page_1", 12 | "title": "http://mockbin.com/", 13 | "pageTimings": { 14 | "onContentLoad": 627.40, 15 | "onLoad": 1266.53 16 | } 17 | } 18 | ], 19 | "entries": [ 20 | { 21 | "startedDateTime": "2015-02-10T07:33:17.146Z", 22 | "time": 181.59, 23 | "request": { 24 | "method": "GET", 25 | "url": "http://mockbin.com/", 26 | "httpVersion": "HTTP/1.1", 27 | "headers": [ 28 | { 29 | "name": "DNT", 30 | "value": "1" 31 | }, 32 | { 33 | "name": "Accept-Encoding", 34 | "value": "gzip, deflate, sdch" 35 | }, 36 | { 37 | "name": "Host", 38 | "value": "mockbin.com" 39 | }, 40 | { 41 | "name": "Connection", 42 | "value": "keep-alive" 43 | } 44 | ], 45 | "queryString": [], 46 | "cookies": [ 47 | { 48 | "name": "foo", 49 | "expires": "2015-02-10T07:33:17.146Z", 50 | "value": "bar", 51 | "httpOnly": false, 52 | "secure": false 53 | } 54 | ], 55 | "headersSize": 482, 56 | "bodySize": 0 57 | }, 58 | "response": { 59 | "status": 200, 60 | "statusText": "OK", 61 | "httpVersion": "HTTP/1.1", 62 | "headers": [ 63 | { 64 | "name": "X-Response-Time", 65 | "value": "3.419ms" 66 | }, 67 | { 68 | "name": "Date", 69 | "value": "Tue, 10 Feb 2015 07:33:16 GMT" 70 | }, 71 | { 72 | "name": "Vary", 73 | "value": "Accept, Accept-Encoding" 74 | }, 75 | { 76 | "name": "X-Powered-By", 77 | "value": "mockbin.com" 78 | }, 79 | { 80 | "name": "Transfer-Encoding", 81 | "value": "chunked" 82 | }, 83 | { 84 | "name": "Content-Type", 85 | "value": "text/html; charset=utf-8" 86 | }, 87 | { 88 | "name": "Content-Encoding", 89 | "value": "gzip" 90 | }, 91 | { 92 | "name": "Connection", 93 | "value": "keep-alive" 94 | } 95 | ], 96 | "cookies": [], 97 | "content": { 98 | "size": 30, 99 | "mimeType": "text/html", 100 | "compression": 0, 101 | "text": "ALL YOUR BASE ARE BELONG TO US" 102 | }, 103 | "redirectURL": "", 104 | "headersSize": 430, 105 | "bodySize": 30 106 | }, 107 | "cache": {}, 108 | "timings": { 109 | "blocked": 0.38, 110 | "dns": -1, 111 | "connect": -1, 112 | "send": 0.05, 113 | "wait": 179.18, 114 | "receive": 1.97, 115 | "ssl": -1 116 | }, 117 | "connection": "161767", 118 | "pageref": "page_1" 119 | } 120 | ] 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Benchmark]: JSON Parsing 2 | 3 | ## Libraries Tested 4 | 5 | - [clarinet](https://www.npmjs.com/package/clarinet) `v0.11.0` 6 | - [jju](https://www.npmjs.com/package/jju) `v1.3.0` 7 | - [json-parse-stream](https://www.npmjs.com/package/json-parse-stream) `v0.0.2` 8 | - [jsonparse](https://www.npmjs.com/package/jsonparse) `v1.2.0` 9 | - [stream-json](https://www.npmjs.com/package/stream-json) `v0.4.1` 10 | - [vuvuzela](https://www.npmjs.com/package/vuvuzela) `v1.0.2` 11 | 12 | **Note**: for a more detailed performance study on why you shouldn't use `clarinet` *(and others)* when you just need `JSON.parse`, please refer to this [article](http://writings.nunojob.com/2011/12/clarinet-sax-based-evented-streaming-json-parser-in-javascript-for-the-browser-and-nodejs.html) 13 | 14 | ## Results 15 | 16 | 17 | ### `Node.js v5.7.x` *(Apr, 02, 2016)* 18 | 19 | ###### Fastest 20 | ``` 21 | JSON.parse x 80,639 ops/sec ±2.14% (88 runs sampled) 22 | ``` 23 | ###### Slowest 24 | ``` 25 | stream-json x 1,775 ops/sec ±1.14% (82 runs sampled) 26 | ``` 27 | ###### Results 28 | ``` 29 | clarinet x 2,636 ops/sec ±2.13% (78 runs sampled) 30 | JSON.parse x 80,639 ops/sec ±2.14% (88 runs sampled) 31 | jju x 7,343 ops/sec ±3.12% (84 runs sampled) 32 | jsonparse x 10,719 ops/sec ±4.54% (45 runs sampled) 33 | json-parse-stream x 2,039 ops/sec ±6.39% (69 runs sampled) 34 | stream-json x 1,775 ops/sec ±1.14% (82 runs sampled) 35 | vuvuzela x 15,644 ops/sec ±4.07% (87 runs sampled) 36 | ``` 37 | 38 | ### `Node.js v4.2.x` *(Nov 5, 2015)* 39 | 40 | ###### Fastest 41 | ``` 42 | JSON.parse x 68.28 ops/sec ±4.43% (59 runs sampled) 43 | ``` 44 | ###### Slowest 45 | ``` 46 | stream-json x 2.75 ops/sec ±7.05% (18 runs sampled) 47 | ``` 48 | ###### Results 49 | ``` 50 | JSON.parse x 68.28 ops/sec ±4.43% (59 runs sampled) 51 | vuvuzela x 14.38 ops/sec ±4.32% (40 runs sampled) 52 | jsonparse x 6.39 ops/sec ±12.12% (20 runs sampled) 53 | jju x 6.08 ops/sec ±15.54% (20 runs sampled) 54 | clarinet x 5.56 ops/sec ±2.93% (32 runs sampled) 55 | json-parse-stream x 4.91 ops/sec ±3.03% (28 runs sampled) 56 | stream-json x 2.75 ops/sec ±7.05% (18 runs sampled) 57 | ``` 58 | 59 | ### `Node.js v0.12.x` *(Jul 24, 2015)* 60 | 61 | ###### Fastest 62 | ``` 63 | JSON.parse x 55,607 ops/sec ±0.70% (93 runs sampled) 64 | ``` 65 | ###### Slowest 66 | ``` 67 | stream-json x 374 ops/sec ±1.98% (76 runs sampled) 68 | ``` 69 | ###### Results 70 | ``` 71 | JSON.parse x 55,607 ops/sec ±0.70% (93 runs sampled) 72 | vuvuzela x 10,932 ops/sec ±0.92% (92 runs sampled) 73 | jju x 4,914 ops/sec ±0.52% (94 runs sampled) 74 | jsonparse x 553 ops/sec ±1.10% (79 runs sampled) 75 | json-parse-stream x 388 ops/sec ±3.31% (69 runs sampled) 76 | clarinet x 386 ops/sec ±2.72% (69 runs sampled) 77 | stream-json x 374 ops/sec ±1.98% (76 runs sampled) 78 | ``` 79 | 80 | 81 | ### `Node.js v0.10.x` *(Jul 24, 2015)* 82 | 83 | ###### Fastest 84 | ``` 85 | JSON.parse x 72,275 ops/sec ±1.55% (91 runs sampled) 86 | ``` 87 | ###### Slowest 88 | ``` 89 | stream-json x 416 ops/sec ±2.22% (78 runs sampled) 90 | ``` 91 | ###### Results 92 | ``` 93 | JSON.parse x 72,275 ops/sec ±1.55% (91 runs sampled) 94 | vuvuzela x 11,009 ops/sec ±1.91% (91 runs sampled) 95 | jju x 3,716 ops/sec ±4.34% (85 runs sampled) 96 | jsonparse x 621 ops/sec ±2.86% (75 runs sampled) 97 | clarinet x 427 ops/sec ±2.40% (72 runs sampled) 98 | json-parse-stream x 426 ops/sec ±2.21% (74 runs sampled) 99 | stream-json x 416 ops/sec ±2.22% (78 runs sampled) 100 | ``` 101 | --------------------------------------------------------------------------------