Document how to get an array of all suite results
I have tried:
suite
.on('complete', function () {
// eslint-disable-next-line babel/no-invalid-this
const benchmarks = Object.values(this);
});
However, here this is an object that contains each suite as {[benchmark index]: results, plus some arbitrary properties}.
I cannot not find anything in the https://benchmarkjs.com/ that says getSuiteResultList or anything along those lines.
The only reasonable way I have found to do this is to built the results array using the cycle event.
suite
.on('cycle', (event) => {
results.push(event.target);
})
.on('complete', () => {
console.log(results);
});
I have a proposal for a code sample that may help the documentation:
const Benchmark = require('benchmark');
const MIN_INPUT_SIZE = 1;
const MAX_INPUT_SIZE = 10000;
const INPUT_SIZE_INCREMENTOR = inputSize => inputSize * 10;
const PRECISION = 2;
for (
let INPUT_SIZE = MIN_INPUT_SIZE;
INPUT_SIZE <= MAX_INPUT_SIZE;
INPUT_SIZE = INPUT_SIZE_INCREMENTOR(INPUT_SIZE)
) {
const results = [];
const suite = new Benchmark.Suite();
const array = [];
const set = new Set();
const map = new Map();
for (let i = 0; i < INPUT_SIZE; ++i) {
array.push(Math.random());
set.add(Math.random());
map.set(Math.random(), true);
}
suite
// add tests
.add('array.includes', () => {
array.includes(Math.random());
})
.add('set.has', () => {
set.has(Math.random());
})
.add('map.has', () => {
map.has(Math.random());
})
// add listeners
.on('start', () => console.log(`\nStarting benchmarks for INPUT_SIZE ${INPUT_SIZE}`))
.on('cycle', event =>
results.push({
name: event.target.name,
hz: event.target.hz,
'margin of error': `±${Number(event.target.stats.rme).toFixed(2)}%`,
'runs sampled': event.target.stats.sample.length,
})
)
.on('complete', function() {
const lowestHz = results.slice().sort((a, b) => a.hz - b.hz)[0].hz;
console.table(
results
.sort((a, b) => b.hz - a.hz)
.map(result => ({
...result,
hz: Math.round(result.hz).toLocaleString(),
numTimesFaster: Math.round((10 ** PRECISION * result.hz) / lowestHz) / 10 ** PRECISION,
}))
.sort((a, b) => a.INPUT_SIZE - b.INPUT_SIZE)
.reduce((acc, { name, ...cur }) => ({ ...acc, [name]: cur }), {})
);
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run({ async: false });
}
This code produces results that look like this:
Starting benchmarks for INPUT_SIZE 1
┌────────────────┬──────────────┬─────────────────┬──────────────┬────────────────┐
│ (index) │ hz │ margin of error │ runs sampled │ numTimesFaster │
├────────────────┼──────────────┼─────────────────┼──────────────┼────────────────┤
│ map.has │ '93,039,281' │ '±1.68%' │ 89 │ 3.11 │
│ array.includes │ '78,448,191' │ '±5.49%' │ 80 │ 2.62 │
│ set.has │ '29,912,341' │ '±1.29%' │ 90 │ 1 │
└────────────────┴──────────────┴─────────────────┴──────────────┴────────────────┘
Fastest is map.has
Starting benchmarks for INPUT_SIZE 10
┌────────────────┬──────────────┬─────────────────┬──────────────┬────────────────┐
│ (index) │ hz │ margin of error │ runs sampled │ numTimesFaster │
├────────────────┼──────────────┼─────────────────┼──────────────┼────────────────┤
│ map.has │ '94,382,136' │ '±1.83%' │ 85 │ 6.32 │
│ array.includes │ '87,067,046' │ '±1.69%' │ 92 │ 5.83 │
│ set.has │ '14,934,322' │ '±5.86%' │ 59 │ 1 │
└────────────────┴──────────────┴─────────────────┴──────────────┴────────────────┘
Fastest is map.has
Starting benchmarks for INPUT_SIZE 100
┌────────────────┬──────────────┬─────────────────┬──────────────┬────────────────┐
│ (index) │ hz │ margin of error │ runs sampled │ numTimesFaster │
├────────────────┼──────────────┼─────────────────┼──────────────┼────────────────┤
│ map.has │ '95,336,202' │ '±1.51%' │ 89 │ 3.82 │
│ array.includes │ '85,730,663' │ '±2.51%' │ 89 │ 3.44 │
│ set.has │ '24,943,802' │ '±0.75%' │ 93 │ 1 │
└────────────────┴──────────────┴─────────────────┴──────────────┴────────────────┘
Fastest is map.has
Starting benchmarks for INPUT_SIZE 1000
┌────────────────┬──────────────┬─────────────────┬──────────────┬────────────────┐
│ (index) │ hz │ margin of error │ runs sampled │ numTimesFaster │
├────────────────┼──────────────┼─────────────────┼──────────────┼────────────────┤
│ map.has │ '91,862,613' │ '±3.26%' │ 85 │ 4.1 │
│ array.includes │ '85,239,920' │ '±1.86%' │ 85 │ 3.81 │
│ set.has │ '22,390,868' │ '±0.74%' │ 93 │ 1 │
└────────────────┴──────────────┴─────────────────┴──────────────┴────────────────┘
Fastest is map.has
Starting benchmarks for INPUT_SIZE 10000
┌────────────────┬──────────────┬─────────────────┬──────────────┬────────────────┐
│ (index) │ hz │ margin of error │ runs sampled │ numTimesFaster │
├────────────────┼──────────────┼─────────────────┼──────────────┼────────────────┤
│ array.includes │ '81,607,364' │ '±7.37%' │ 82 │ 4.82 │
│ map.has │ '53,299,601' │ '±5.18%' │ 53 │ 3.15 │
│ set.has │ '16,922,667' │ '±1.85%' │ 88 │ 1 │
└────────────────┴──────────────┴─────────────────┴──────────────┴────────────────┘
Fastest is array.includes
The major features of this code:
- It produces a concise summary of a single test's results.
- It shows how a test performs at different orders of magnitude.
Is this worth including in the documentation? If so, which section would be most appropriate? I think that the example on the main page https://benchmarkjs.com/ is good because it is so simple. Maybe there could be a section of examples of different complextity?
@jdalton @gajus