Skip to content

Commit b7bc6d6

Browse files
committed
Add benchmark comparison tool.
- Currently supports markdown table output. - Can output environment. - Can output ops/s or ops/s with relative differences.
1 parent f8b9aa6 commit b7bc6d6

File tree

5 files changed

+223
-2
lines changed

5 files changed

+223
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- Support benchmarks in Karma tests.
55
- Support test environment in EARL output.
66
- Support benchmark output in EARL output.
7+
- Benchmark comparison tool.
78

89
### Changed
910
- Change EARL Assertor to Digital Bazaar, Inc.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ details:
462462

463463
See `tests/test.js` for more `TEST_ENV` control and options.
464464

465-
These reports can be compared with the `tests/benchmark-compare` tool and at
466-
the [JSON-LD Benchmarks][] site.
465+
These reports can be compared with the `benchmarks/compare/` tool and at the
466+
[JSON-LD Benchmarks][] site.
467467

468468
[Digital Bazaar]: https://digitalbazaar.com/
469469

benchmarks/compare/.eslintrc.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
env: {
3+
commonjs: true,
4+
node: true,
5+
es2020: true
6+
},
7+
extends: 'eslint-config-digitalbazaar',
8+
root: true
9+
};

benchmarks/compare/compare.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env node
2+
3+
import yargs from 'yargs';
4+
import {hideBin} from 'yargs/helpers';
5+
import {promises as fs} from 'node:fs';
6+
import {table} from 'table';
7+
import {markdownTable} from 'markdown-table';
8+
import commonPathPrefix from 'common-path-prefix';
9+
10+
yargs(hideBin(process.argv))
11+
.alias('h', 'help')
12+
.option('verbose', {
13+
alias: 'v',
14+
type: 'count',
15+
description: 'Run with verbose logging'
16+
})
17+
.option('relative', {
18+
alias: 'r',
19+
type: 'boolean',
20+
default: false,
21+
description: 'Show % relative difference'
22+
})
23+
.option('format', {
24+
alias: 'f',
25+
choices: ['markdown'],
26+
default: 'markdown',
27+
description: 'Output format'
28+
})
29+
.option('env', {
30+
alias: 'e',
31+
choices: ['none', 'all', 'combined'],
32+
default: 'none',
33+
description: 'Output environment format'
34+
})
35+
.command(
36+
'$0 <file...>',
37+
'compare JSON-LD benchmark files', () => {},
38+
async (argv) => {
39+
return compare(argv);
40+
})
41+
.parse();
42+
43+
async function compare({
44+
env,
45+
file,
46+
format,
47+
relative,
48+
verbose
49+
}) {
50+
const contents = await Promise.all(file.map(async f => ({
51+
fn: f,
52+
content: await fs.readFile(f, 'utf8')
53+
})));
54+
const results = contents
55+
.map(c => ({
56+
fn: c.fn,
57+
content: JSON.parse(c.content),
58+
// map of test id => assertion
59+
testMap: new Map()
60+
}))
61+
.map(c => ({
62+
...c,
63+
// FIXME process properly
64+
env: c.content['@included'][0],
65+
label: c.content['@included'][0]['jldb:label']
66+
}));
67+
//console.log(JSON.stringify(results, null, 2));
68+
// order of tests found in each result set
69+
// TODO: provider interleaved mode for new results in
70+
const seen = new Set();
71+
const ordered = [];
72+
results.forEach(r => {
73+
r.content.subjectOf.forEach(a => {
74+
//console.log(a);
75+
const t = a['earl:test'];
76+
if(!seen.has(t)) {
77+
ordered.push(t);
78+
}
79+
seen.add(t);
80+
r.testMap.set(t, a);
81+
});
82+
});
83+
//console.log(ordered);
84+
const tprefixlen = commonPathPrefix(ordered).length;
85+
function hz(a) {
86+
return a['jldb:result']['jldb:hz'];
87+
}
88+
function rfmt(base, a) {
89+
return relative ? (100*(a-base)/base) : a;
90+
}
91+
const compared = ordered.map(t => [
92+
t.slice(tprefixlen),
93+
hz(results[0].testMap.get(t)).toFixed(2),
94+
...results.slice(1)
95+
.map(r => rfmt(
96+
hz(results[0].testMap.get(t)),
97+
hz(r.testMap.get(t))))
98+
.map(d => relative ? d.toFixed(2) + '%' : d.toFixed(2))
99+
]);
100+
//console.log(compared);
101+
//console.log(results);
102+
const fnprefixlen = commonPathPrefix(file).length;
103+
console.log('## Comparison');
104+
console.log(markdownTable([
105+
[
106+
'Test',
107+
...results.map(r => r.label || r.fn.slice(fnprefixlen))
108+
],
109+
...compared
110+
], {
111+
align: [
112+
'l',
113+
...results.map(r => 'r')
114+
]
115+
}));
116+
console.log();
117+
if(relative) {
118+
console.log('> base ops/s and relative difference (higher is better)');
119+
} else {
120+
console.log('> ops/s (higher is better)');
121+
}
122+
123+
const envProps = [
124+
['Label', 'jldb:label'],
125+
['Arch', 'jldb:arch'],
126+
['CPU', 'jldb:cpu'],
127+
['CPUs', 'jldb:cpuCount'],
128+
['Platform', 'jldb:platform'],
129+
['Runtime', 'jldb:runtime'],
130+
['Runtime Version', 'jldb:runtimeVersion'],
131+
['Comment', 'jldb:comment']
132+
];
133+
134+
if(env === 'all') {
135+
console.log();
136+
console.log('## Environment');
137+
console.log(markdownTable([
138+
envProps.map(p => p[0]),
139+
...results.map(r => envProps.map(p => r.env[p[1]] || ''))
140+
]));
141+
}
142+
143+
if(env === 'combined') {
144+
console.log();
145+
console.log('## Environment');
146+
function envline(key, prop) {
147+
const values = new Set(results
148+
.map(r => r.env[prop])
149+
.filter(v => v !== undefined)
150+
);
151+
return [key, values.size ? [...values].join(', ') : []];
152+
}
153+
console.log(markdownTable([
154+
['Key', 'Values'],
155+
...envProps
156+
.map(p => envline(p[0], p[1]))
157+
.filter(p => p[1].length)
158+
]));
159+
}
160+
}

benchmarks/compare/package.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"name": "jsonld-benchmarks-compare",
3+
"version": "0.0.1-0",
4+
"private": true,
5+
"description": "A JSON-LD benchmark comparison tool.",
6+
"homepage": "https://github.com/digitalbazaar/jsonld.js",
7+
"author": {
8+
"name": "Digital Bazaar, Inc.",
9+
"email": "[email protected]",
10+
"url": "https://digitalbazaar.com/"
11+
},
12+
"contributors": [
13+
"Dave Longley <[email protected]>",
14+
"David I. Lehn <[email protected]>"
15+
],
16+
"repository": {
17+
"type": "git",
18+
"url": "https://github.com/digitalbazaar/jsonld.js"
19+
},
20+
"bugs": {
21+
"url": "https://github.com/digitalbazaar/jsonld.js/issues",
22+
"email": "[email protected]"
23+
},
24+
"license": "BSD-3-Clause",
25+
"type": "module",
26+
"main": "compare.js",
27+
"dependencies": {
28+
"common-path-prefix": "^3.0.0",
29+
"markdown-table": "^3.0.2",
30+
"yargs": "^17.4.0"
31+
},
32+
"devDependencies": {
33+
"eslint": "^8.11.0",
34+
"eslint-config-digitalbazaar": "^2.8.0"
35+
},
36+
"engines": {
37+
"node": ">=12"
38+
},
39+
"keywords": [
40+
"JSON",
41+
"JSON-LD",
42+
"Linked Data",
43+
"RDF",
44+
"Semantic Web",
45+
"jsonld",
46+
"benchmark"
47+
],
48+
"scripts": {
49+
"lint": "eslint *.js"
50+
}
51+
}

0 commit comments

Comments
 (0)