Skip to content

Commit 8c85dec

Browse files
committed
chore: Add comment-json and the current jsonlint implementation to the performance comparison
1 parent 5574ef1 commit 8c85dec

File tree

6 files changed

+107
-24
lines changed

6 files changed

+107
-24
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,15 +268,13 @@ If you want to retain comments or whitespace for pretty-printing, for example, s
268268

269269
### Performance
270270

271-
This is a part of an output from the [parser benchmark], when parsing a 4.2 KB formatted string ([package.json](./package.json)) with Node.js 10.15.3:
271+
This is a part of an output from the [parser benchmark], when parsing a 4.2 KB formatted string ([package.json](./package.json)) with Node.js 12.14.0:
272272

273-
the built-in parser x 68,212 ops/sec ±0.86% (87 runs sampled)
274-
the pure jju parser x 10,234 ops/sec ±1.08% (89 runs sampled)
275-
the extended jju parser x 10,210 ops/sec ±1.26% (88 runs sampled)
276-
the tokenizable jju parser x 8,832 ops/sec ±0.92% (89 runs sampled)
277-
the tokenizing jju parser x 7,911 ops/sec ±1.05% (86 runs sampled)
273+
jsonlint using native JSON.parse x 97,109 ops/sec ±0.81% (93 runs sampled)
274+
jsonlint using hand-coded parser x 7,256 ops/sec ±0.54% (90 runs sampled)
275+
jsonlint using tokenising parser x 6,387 ops/sec ±0.44% (88 runs sampled)
278276

279-
A custom JSON parser is [a lot slower] than the built-in one. However, it is more important to have a [clear error reporting] than the highest speed in scenarios like parsing configuration files. Extending the parser with the support for comments and single-quoted strings does not affect the performance. Making the parser collect tokens and their locations decreases the performance a bit.
277+
A custom JSON parser is [a lot slower] than the built-in one. However, it is more important to have a [clear error reporting] than the highest speed in scenarios like parsing configuration files. (For better error-reporting, the speed can be preserved by using the native parser initially and re-parsing with another parser only in case of failure.) Features like comments or JSON5 are also helpful in configuration files. Tokens preserve the complete input and can be used for pretty-printing without losing the comments.
280278

281279
### Error Handling
282280

benchmarks/fail.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { parse: jjuParse } = require('./jju/pure')
66
const { parse: pegjsParse } = require('./pegjs/pure')
77
const jisonParser = require('./jison/pure').parser
88
const JSON5 = require('json5')
9+
const { parse: parseWithComments } = require('comment-json')
910

1011
const inputSources = [
1112
`{
@@ -184,6 +185,10 @@ function parseJju () {
184185
}
185186
}
186187

188+
function parseCommentJson () {
189+
parseWithComments(inputSource)
190+
}
191+
187192
function improvePegjsError (error) {
188193
const { message, location } = error
189194
const { line, column, offset } = location.start
@@ -237,6 +242,7 @@ for (const test of inputSources) {
237242
.add('the chevrotain parser', parseChevrotain)
238243
.add('the hand-built parser', parseHandbuilt)
239244
.add('the jju parser', parseJju)
245+
.add('the comment-json parser', parseCommentJson)
240246
.add('the pegjs parser', parsePegjs)
241247
.add('the jison parser', parseJison)
242248
.add('the JSON5 parser', parseJSON5)

benchmarks/package-lock.json

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmarks/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"devDependencies": {
88
"benchmark": "2.1.4",
99
"chevrotain": "6.5.0",
10+
"comment-json": "2.3.1",
1011
"jison": "0.4.18",
1112
"json-to-ast": "2.1.0",
1213
"json5": "2.1.1",

benchmarks/parse.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const handbuiltParse = require('./hand-built/pure')
1515
const handbuiltExtendedParse = require('./hand-built/pure')
1616
const astParse = require('json-to-ast')
1717
const JSON5 = require('json5')
18+
const { parse: parseWithComments } = require('comment-json')
19+
const { parse: parseThis, tokenize: tokenizeThis } = require('..')
1820

1921
const pkg = require('../package')
2022
const input = JSON.stringify(pkg, undefined, 2)
@@ -58,6 +60,22 @@ function parseTokenisingJju () {
5860
})
5961
}
6062

63+
function parseCommentJson () {
64+
parseWithComments(input)
65+
}
66+
67+
function parseCurrentStandard () {
68+
parseThis(input)
69+
}
70+
71+
function parseCurrentExtended () {
72+
parseThis(input, { mode: 'json5' })
73+
}
74+
75+
function parseCurrentTokenising () {
76+
tokenizeThis(input, { mode: 'json5' })
77+
}
78+
6179
function parsePurePegjs () {
6280
pegjsParse(input)
6381
}
@@ -88,13 +106,17 @@ createSuite(`Parsing JSON data ${input.length} characters long using`)
88106
.add('the built-in parser', parseBuiltIn)
89107
.add('the pure chevrotain parser', parsePureChevrotain)
90108
.add('the extended chevrotain parser', parseExtendedChevrotain)
109+
.add('the standard jsonlint parser', parseCurrentStandard)
110+
.add('the extended jsonlint parser', parseCurrentExtended)
111+
.add('the tokenising jsonlint parser', parseCurrentTokenising)
91112
.add('the pure hand-built parser', parseHandbuilt)
92113
.add('the extended hand-built parser', parseExtendedHandbuilt)
93114
.add('the AST parser', parseAST)
94115
.add('the pure jju parser', parsePureJju)
95116
.add('the extended jju parser', parseExtendedJju)
96117
.add('the tokenisable jju parser', parseTokenisableJju)
97118
.add('the tokenising jju parser', parseTokenisingJju)
119+
.add('the comments-enabled parser', parseCommentJson)
98120
.add('the pure pegjs parser', parsePurePegjs)
99121
.add('the extended pegjs parser', parseExtendedPegjs)
100122
.add('the pure jison parser', parsePureJison)

benchmarks/results/performance.md

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,27 @@ Results
2727

2828
This is a result of the [benchmark] run by `npm run benchmarks`. The numbers should be understood as relative ones:
2929

30-
Parsing JSON data 4479 characters long using:
31-
the built-in parser x 67,113 ops/sec ±0.79% (89 runs sampled)
32-
the pure chevrotain parser x 15,446 ops/sec ±1.30% (90 runs sampled)
33-
the extended chevrotain parser x 14,168 ops/sec ±1.23% (88 runs sampled)
34-
the pure hand-built parser x 9,755 ops/sec ±0.92% (89 runs sampled)
35-
the extended hand-built parser x 9,633 ops/sec ±1.13% (88 runs sampled)
36-
the AST parser x 9,768 ops/sec ±0.83% (89 runs sampled)
37-
the pure jju parser x 10,178 ops/sec ±0.97% (84 runs sampled)
38-
the extended jju parser x 10,204 ops/sec ±1.13% (88 runs sampled)
39-
the tokenisable jju parser x 8,904 ops/sec ±1.01% (88 runs sampled)
40-
the tokenising jju parser x 6,750 ops/sec ±0.97% (88 runs sampled)
41-
the pure pegjs parser x 3,083 ops/sec ±0.95% (89 runs sampled)
42-
the extended pegjs parser x 2,786 ops/sec ±1.12% (89 runs sampled)
43-
the pure jison parser x 3,033 ops/sec ±1.19% (88 runs sampled)
44-
the extended jison parser x 2,810 ops/sec ±0.65% (88 runs sampled)
45-
the JSON5 parser x 2,085 ops/sec ±0.45% (91 runs sampled)
46-
The fastest one was the built-in parser.
30+
Parsing JSON data 4589 characters long using:
31+
the built-in parser x 97,039 ops/sec ±0.69% (92 runs sampled)
32+
the pure chevrotain parser x 11,981 ops/sec ±0.86% (87 runs sampled)
33+
the extended chevrotain parser x 11,183 ops/sec ±0.54% (88 runs sampled)
34+
the standard jsonlint parser x 97,109 ops/sec ±0.81% (93 runs sampled)
35+
the extended jsonlint parser x 7,256 ops/sec ±0.54% (90 runs sampled)
36+
the tokenising jsonlint parser x 6,387 ops/sec ±0.44% (88 runs sampled)
37+
the pure hand-built parser x 7,508 ops/sec ±0.49% (86 runs sampled)
38+
the extended hand-built parser x 7,517 ops/sec ±0.45% (90 runs sampled)
39+
the AST parser x 8,008 ops/sec ±0.90% (85 runs sampled)
40+
the pure jju parser x 7,505 ops/sec ±0.64% (89 runs sampled)
41+
the extended jju parser x 7,352 ops/sec ±0.45% (90 runs sampled)
42+
the tokenisable jju parser x 6,636 ops/sec ±0.46% (89 runs sampled)
43+
the tokenising jju parser x 5,373 ops/sec ±0.54% (89 runs sampled)
44+
the comments-enabled parser x 6,258 ops/sec ±0.95% (88 runs sampled)
45+
the pure pegjs parser x 2,803 ops/sec ±0.58% (88 runs sampled)
46+
the extended pegjs parser x 2,526 ops/sec ±0.74% (87 runs sampled)
47+
the pure jison parser x 2,460 ops/sec ±0.49% (89 runs sampled)
48+
the extended jison parser x 2,195 ops/sec ±0.63% (88 runs sampled)
49+
the JSON5 parser x 1,660 ops/sec ±0.84% (90 runs sampled)
50+
The fastest one was the built-in parser,the standard jsonlint parser.
4751

4852
I looked further at capabilities and licenses of the parsers.
4953

@@ -86,6 +90,13 @@ I looked further at capabilities and licenses of the parsers.
8690
* Supports `reviver` for the full compatibility with JSON.parse.
8791
* Can generate tokens to analyse, modify and update the original JSON input.
8892

93+
[comment-json]
94+
--------------
95+
96+
* Very fast one.
97+
* Supports `reviver` for the full compatibility with JSON.parse.
98+
* Supports CJSON - JSON with JavaScript-like comments.
99+
89100
[PEG.JS]
90101
--------
91102

@@ -105,13 +116,20 @@ I looked further at capabilities and licenses of the parsers.
105116
* Hand-built parser implementing the [JSON5 specification]. Extensions mentioned above were included, and even more, like trailing commas or multi-line strings. No support for pure JSON.
106117
* Slower one.
107118

119+
[JSONLint]
120+
----------
121+
122+
This entry is here just to compare the current implementation to the original "contenders". Based on the [evaluation] results, the current JSONLint uses a hand-coded parser based on [JJU].
123+
108124
[tested with a JSON grammar]: https://sap.github.io/chevrotain/performance/
109125
[quality of error reporting]: ./errorReportingQuality.md
126+
[evaluation]: ./evaluation.md
110127
[benchmark]: ../parse.js
111128
[Built-in]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
112129
[Chevrotain]: https://github.com/SAP/chevrotain
113130
[Hand-built]: https://github.com/sap/chevrotain/blob/gh-pages/performance/jsonParsers/handbuilt/handbuilt.js
114131
[JJU]: http://rlidwka.github.io/jju/
132+
[comment-json]: https://github.com/kaelzhang/node-comment-json
115133
[AST]: https://github.com/vtrushin/json-to-ast
116134
[PEG.JS]: http://pegjs.org/
117135
[Jison]: http://zaach.github.io/jison/

0 commit comments

Comments
 (0)