Skip to content

Commit f376963

Browse files
authored
build(benchmarks): replace benchmark with tinybench (#156)
1 parent 0248707 commit f376963

File tree

8 files changed

+144
-111
lines changed

8 files changed

+144
-111
lines changed

README.md

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,54 +91,76 @@ Scans a given object for prototype properties where:
9191
Machine: 2.4 Ghz 14-core Intel Core i7-13650HX
9292

9393
```
94+
v22.20.0
95+
9496
9597
> node valid.js
9698
97-
JSON.parse x 1,866,229 ops/sec ±1.91% (86 runs sampled)
98-
JSON.parse proto x 1,237,402 ops/sec ±1.32% (95 runs sampled)
99-
secure-json-parse parse x 1,693,973 ops/sec ±0.99% (94 runs sampled)
100-
secure-json-parse parse proto x 1,864,139 ops/sec ±0.86% (95 runs sampled)
101-
secure-json-parse safeParse x 1,703,452 ops/sec ±0.46% (91 runs sampled)
102-
secure-json-parse safeParse proto x 1,116,725 ops/sec ±0.62% (94 runs sampled)
103-
JSON.parse reviver x 295,223 ops/sec ±0.39% (100 runs sampled)
104-
Fastest is secure-json-parse parse proto
99+
valid benchmark
100+
┌─────────┬─────────────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐
101+
│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
102+
├─────────┼─────────────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤
103+
│ 0 │ 'JSON.parse' │ '610.10 ± 0.39%' │ '600.00 ± 0.00' │ '1740515 ± 0.02%' │ '1666667 ± 0' │ 1639075 │
104+
│ 1 │ 'JSON.parse proto' │ '875.42 ± 0.39%' │ '800.00 ± 0.00' │ '1210508 ± 0.03%' │ '1250000 ± 0' │ 1142308 │
105+
│ 2 │ 'secure-json-parse parse' │ '634.34 ± 0.32%' │ '600.00 ± 0.00' │ '1624445 ± 0.01%' │ '1666667 ± 0' │ 1576434 │
106+
│ 3 │ 'secure-json-parse parse proto' │ '657.25 ± 0.42%' │ '600.00 ± 0.00' │ '1666577 ± 0.03%' │ '1666667 ± 0' │ 1521499 │
107+
│ 4 │ 'secure-json-parse safeParse' │ '646.03 ± 1.68%' │ '600.00 ± 0.00' │ '1622543 ± 0.02%' │ '1666667 ± 0' │ 1547914 │
108+
│ 5 │ 'secure-json-parse safeParse proto' │ '912.34 ± 0.20%' │ '900.00 ± 0.00' │ '1122250 ± 0.02%' │ '1111111 ± 0' │ 1096080 │
109+
│ 6 │ 'JSON.parse reviver' │ '3448.5 ± 0.59%' │ '3200.0 ± 0.00' │ '300173 ± 0.04%' │ '312500 ± 0' │ 289982 │
110+
└─────────┴─────────────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘
105111
106112
107113
> node ignore.js
108114
109-
JSON.parse x 1,227,994 ops/sec ±1.05% (90 runs sampled)
110-
secure-json-parse parse x 1,184,011 ops/sec ±0.66% (95 runs sampled)
111-
secure-json-parse safeParse x 1,123,041 ops/sec ±1.12% (92 runs sampled)
112-
reviver x 196,637 ops/sec ±0.50% (99 runs sampled)
113-
Fastest is JSON.parse
115+
ignore benchmark
116+
┌─────────┬───────────────────────────────┬──────────────────┬───────────────────┬────────────────────────┬────────────────────────┬─────────┐
117+
│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
118+
├─────────┼───────────────────────────────┼──────────────────┼───────────────────┼────────────────────────┼────────────────────────┼─────────┤
119+
│ 0 │ 'JSON.parse' │ '897.15 ± 0.53%' │ '800.00 ± 0.00' │ '1201546 ± 0.03%' │ '1250000 ± 0' │ 1114647 │
120+
│ 1 │ 'secure-json-parse parse' │ '891.22 ± 0.45%' │ '800.00 ± 0.00' │ '1168492 ± 0.02%' │ '1250000 ± 0' │ 1122056 │
121+
│ 2 │ 'secure-json-parse safeParse' │ '938.74 ± 0.56%' │ '900.00 ± 0.00' │ '1106881 ± 0.02%' │ '1111111 ± 0' │ 1065255 │
122+
│ 3 │ 'reviver' │ '5741.8 ± 0.79%' │ '4900.0 ± 100.00' │ '188823 ± 0.08%' │ '204082 ± 4252' │ 174162 │
123+
└─────────┴───────────────────────────────┴──────────────────┴───────────────────┴────────────────────────┴────────────────────────┴─────────┘
114124
115125
116126
> node no__proto__.js
117127
118-
JSON.parse x 1,183,590 ops/sec ±0.43% (93 runs sampled)
119-
secure-json-parse parse x 1,053,759 ops/sec ±0.76% (97 runs sampled)
120-
secure-json-parse safeParse x 1,066,295 ops/sec ±0.60% (95 runs sampled)
121-
reviver x 186,683 ops/sec ±0.61% (94 runs sampled)
122-
Fastest is JSON.parse
128+
no __proto__ benchmark
129+
┌─────────┬───────────────────────────────┬──────────────────┬───────────────────┬────────────────────────┬────────────────────────┬─────────┐
130+
│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
131+
├─────────┼───────────────────────────────┼──────────────────┼───────────────────┼────────────────────────┼────────────────────────┼─────────┤
132+
│ 0 │ 'JSON.parse' │ '930.41 ± 0.56%' │ '800.00 ± 0.00' │ '1154630 ± 0.03%' │ '1250000 ± 0' │ 1074798 │
133+
│ 1 │ 'secure-json-parse parse' │ '996.09 ± 0.27%' │ '900.00 ± 0.00' │ '1039752 ± 0.02%' │ '1111111 ± 0' │ 1003921 │
134+
│ 2 │ 'secure-json-parse safeParse' │ '1050.5 ± 7.38%' │ '900.00 ± 0.00' │ '1038060 ± 0.02%' │ '1111111 ± 0' │ 951942 │
135+
│ 3 │ 'reviver' │ '5424.7 ± 3.23%' │ '5100.0 ± 100.00' │ '192362 ± 0.05%' │ '196078 ± 3922' │ 184341 │
136+
└─────────┴───────────────────────────────┴──────────────────┴───────────────────┴────────────────────────┴────────────────────────┴─────────┘
123137
124138
125139
> node remove.js
126140
127-
JSON.parse x 1,229,886 ops/sec ±1.43% (90 runs sampled)
128-
secure-json-parse parse x 506,756 ops/sec ±0.39% (95 runs sampled)
129-
secure-json-parse safeParse x 1,136,082 ops/sec ±0.84% (97 runs sampled)
130-
reviver x 185,631 ops/sec ±1.09% (96 runs sampled)
131-
Fastest is JSON.parse
141+
remove benchmark
142+
┌─────────┬───────────────────────────────┬──────────────────┬───────────────────┬────────────────────────┬────────────────────────┬─────────┐
143+
│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
144+
├─────────┼───────────────────────────────┼──────────────────┼───────────────────┼────────────────────────┼────────────────────────┼─────────┤
145+
│ 0 │ 'JSON.parse' │ '927.86 ± 0.51%' │ '800.00 ± 0.00' │ '1161336 ± 0.03%' │ '1250000 ± 0' │ 1077745 │
146+
│ 1 │ 'secure-json-parse parse' │ '1968.1 ± 0.51%' │ '1900.0 ± 100.00' │ '525418 ± 0.02%' │ '526316 ± 26316' │ 508117 │
147+
│ 2 │ 'secure-json-parse safeParse' │ '930.60 ± 0.19%' │ '900.00 ± 0.00' │ '1103037 ± 0.02%' │ '1111111 ± 0' │ 1074579 │
148+
│ 3 │ 'reviver' │ '5531.4 ± 0.36%' │ '5100.0 ± 100.00' │ '187392 ± 0.06%' │ '196078 ± 3922' │ 180786 │
149+
└─────────┴───────────────────────────────┴──────────────────┴───────────────────┴────────────────────────┴────────────────────────┴─────────┘
132150
133151
134152
> node throw.js
135153
136-
JSON.parse valid x 1,252,559 ops/sec ±1.04% (94 runs sampled)
137-
JSON.parse error x 133,036 ops/sec ±1.35% (73 runs sampled)
138-
secure-json-parse parse x 305,759 ops/sec ±0.80% (93 runs sampled)
139-
secure-json-parse safeParse x 351,419 ops/sec ±0.85% (97 runs sampled)
140-
reviver x 123,542 ops/sec ±0.46% (77 runs sampled)
141-
Fastest is JSON.parse valid
154+
throw benchmark
155+
┌─────────┬───────────────────────────────┬──────────────────┬───────────────────┬────────────────────────┬────────────────────────┬─────────┐
156+
│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
157+
├─────────┼───────────────────────────────┼──────────────────┼───────────────────┼────────────────────────┼────────────────────────┼─────────┤
158+
│ 0 │ 'JSON.parse valid' │ '908.52 ± 0.54%' │ '800.00 ± 0.00' │ '1178218 ± 0.03%' │ '1250000 ± 0' │ 1100690 │
159+
│ 1 │ 'JSON.parse error' │ '7993.2 ± 0.54%' │ '7600.0 ± 200.00' │ '128668 ± 0.06%' │ '131579 ± 3374' │ 125108 │
160+
│ 2 │ 'secure-json-parse parse' │ '3436.4 ± 2.67%' │ '3100.0 ± 100.00' │ '312206 ± 0.05%' │ '322581 ± 10081' │ 291001 │
161+
│ 3 │ 'secure-json-parse safeParse' │ '2800.9 ± 0.33%' │ '2700.0 ± 0.00' │ '364670 ± 0.03%' │ '370370 ± 0' │ 357026 │
162+
│ 4 │ 'reviver' │ '9045.6 ± 1.12%' │ '8300.0 ± 200.00' │ '115581 ± 0.08%' │ '120482 ± 2975' │ 110552 │
163+
└─────────┴───────────────────────────────┴──────────────────┴───────────────────┴────────────────────────┴────────────────────────┴─────────┘
142164
```
143165

144166
## Acknowledgments

benchmarks/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
ignore-scripts=true
12
package-lock=false

benchmarks/ignore.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
'use strict'
22

3-
const Benchmark = require('benchmark')
3+
const { Bench } = require('tinybench')
44
const sjson = require('..')
55

66
const internals = {
77
text: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
88
}
99

10-
const suite = new Benchmark.Suite()
10+
internals.reviver = function (_key, value) {
11+
return value
12+
}
1113

12-
suite
14+
const benchmark = new Bench({
15+
name: 'ignore benchmark',
16+
iterations: 10000,
17+
warmupIterations: 100
18+
})
19+
20+
benchmark
1321
.add('JSON.parse', () => {
1422
JSON.parse(internals.text)
1523
})
@@ -22,14 +30,8 @@ suite
2230
.add('reviver', () => {
2331
JSON.parse(internals.text, internals.reviver)
2432
})
25-
.on('cycle', (event) => {
26-
console.log(String(event.target))
27-
})
28-
.on('complete', function () {
29-
console.log('Fastest is ' + this.filter('fastest').map('name'))
33+
.run()
34+
.then(() => {
35+
console.log(benchmark.name)
36+
console.table(benchmark.table())
3037
})
31-
.run({ async: true })
32-
33-
internals.reviver = function (_key, value) {
34-
return value
35-
}

benchmarks/no__proto__.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
'use strict'
22

3-
const Benchmark = require('benchmark')
3+
const { Bench } = require('tinybench')
44
const sjson = require('..')
55

66
const internals = {
77
text: '{ "a": 5, "b": 6, "proto": { "x": 7 }, "c": { "d": 0, "e": "text", "\\u005f\\u005fproto": { "y": 8 }, "f": { "g": 2 } } }',
88
suspectRx: /"(?:_|\\u005f)(?:_|\\u005f)(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006f)(?:t|\\u0074)(?:o|\\u006f)(?:_|\\u005f)(?:_|\\u005f)"/
99
}
1010

11-
const suite = new Benchmark.Suite()
11+
internals.reviver = function (key, value) {
12+
if (key.match(internals.suspectRx)) {
13+
return undefined
14+
}
1215

13-
suite
16+
return value
17+
}
18+
19+
const benchmark = new Bench({
20+
name: 'no __proto__ benchmark',
21+
iterations: 10000,
22+
warmupIterations: 100
23+
})
24+
25+
benchmark
1426
.add('JSON.parse', () => {
1527
JSON.parse(internals.text)
1628
})
@@ -23,18 +35,8 @@ suite
2335
.add('reviver', () => {
2436
JSON.parse(internals.text, internals.reviver)
2537
})
26-
.on('cycle', (event) => {
27-
console.log(String(event.target))
28-
})
29-
.on('complete', function () {
30-
console.log('Fastest is ' + this.filter('fastest').map('name'))
38+
.run()
39+
.then(() => {
40+
console.log(benchmark.name)
41+
console.table(benchmark.table())
3142
})
32-
.run({ async: true })
33-
34-
internals.reviver = function (key, value) {
35-
if (key.match(internals.suspectRx)) {
36-
return undefined
37-
}
38-
39-
return value
40-
}

benchmarks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
"all": "node --version && npm run valid && npm run ignore && npm run no_proto && npm run remove && npm run throw"
1111
},
1212
"dependencies": {
13-
"benchmark": "^2.1.4"
13+
"tinybench": "^5.0.1"
1414
}
1515
}

benchmarks/remove.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
'use strict'
22

3-
const Benchmark = require('benchmark')
3+
const { Bench } = require('tinybench')
44
const sjson = require('..')
55

66
const internals = {
77
text: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
88
}
99

10-
const suite = new Benchmark.Suite()
10+
internals.reviver = function (key, value) {
11+
if (key === '__proto__') {
12+
return undefined
13+
}
1114

12-
suite
15+
return value
16+
}
17+
18+
const benchmark = new Bench({
19+
name: 'remove benchmark',
20+
iterations: 10000,
21+
warmupIterations: 100
22+
})
23+
24+
benchmark
1325
.add('JSON.parse', () => {
1426
JSON.parse(internals.text)
1527
})
@@ -22,18 +34,8 @@ suite
2234
.add('reviver', () => {
2335
JSON.parse(internals.text, internals.reviver)
2436
})
25-
.on('cycle', (event) => {
26-
console.log(String(event.target))
27-
})
28-
.on('complete', function () {
29-
console.log('Fastest is ' + this.filter('fastest').map('name'))
37+
.run()
38+
.then(() => {
39+
console.log(benchmark.name)
40+
console.table(benchmark.table())
3041
})
31-
.run({ async: true })
32-
33-
internals.reviver = function (key, value) {
34-
if (key === '__proto__') {
35-
return undefined
36-
}
37-
38-
return value
39-
}

benchmarks/throw.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
'use strict'
22

3-
const Benchmark = require('benchmark')
3+
const { Bench } = require('tinybench')
44
const sjson = require('..')
55

66
const internals = {
77
text: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }',
88
invalid: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } } }'
99
}
1010

11-
const suite = new Benchmark.Suite()
11+
internals.reviver = function (key, value) {
12+
if (key === '__proto__') {
13+
throw new Error('kaboom')
14+
}
1215

13-
suite
16+
return value
17+
}
18+
19+
const benchmark = new Bench({
20+
name: 'throw benchmark',
21+
iterations: 10000,
22+
warmupIterations: 100
23+
})
24+
25+
benchmark
1426
.add('JSON.parse valid', () => {
1527
JSON.parse(internals.text)
1628
})
@@ -32,18 +44,8 @@ suite
3244
JSON.parse(internals.invalid, internals.reviver)
3345
} catch { }
3446
})
35-
.on('cycle', (event) => {
36-
console.log(String(event.target))
37-
})
38-
.on('complete', function () {
39-
console.log('Fastest is ' + this.filter('fastest').map('name'))
47+
.run()
48+
.then(() => {
49+
console.log(benchmark.name)
50+
console.table(benchmark.table())
4051
})
41-
.run({ async: true })
42-
43-
internals.reviver = function (key, value) {
44-
if (key === '__proto__') {
45-
throw new Error('kaboom')
46-
}
47-
48-
return value
49-
}

benchmarks/valid.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
'use strict'
22

3-
const Benchmark = require('benchmark')
3+
const { Bench } = require('tinybench')
44
const sjson = require('..')
55

66
const internals = {
77
text: '{ "a": 5, "b": 6, "c": { "d": 0, "e": "text", "f": { "g": 2 } } }',
88
proto: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
99
}
1010

11-
const suite = new Benchmark.Suite()
11+
internals.reviver = function (key, value) {
12+
if (key === '__proto__') {
13+
return undefined
14+
}
1215

13-
suite
16+
return value
17+
}
18+
19+
const benchmark = new Bench({
20+
name: 'valid benchmark',
21+
iterations: 10000,
22+
warmupIterations: 100
23+
})
24+
25+
benchmark
1426
.add('JSON.parse', () => {
1527
JSON.parse(internals.text)
1628
})
@@ -32,18 +44,8 @@ suite
3244
.add('JSON.parse reviver', () => {
3345
JSON.parse(internals.text, internals.reviver)
3446
})
35-
.on('cycle', (event) => {
36-
console.log(String(event.target))
37-
})
38-
.on('complete', function () {
39-
console.log('Fastest is ' + this.filter('fastest').map('name'))
47+
.run()
48+
.then(() => {
49+
console.log(benchmark.name)
50+
console.table(benchmark.table())
4051
})
41-
.run({ async: true })
42-
43-
internals.reviver = function (key, value) {
44-
if (key === '__proto__') {
45-
return undefined
46-
}
47-
48-
return value
49-
}

0 commit comments

Comments
 (0)