JavaScript Benchmarking
Benchmarking JavaScript code without convulated dashboards?
JSPerf was the go-to tool for casually benchmarking JavaScript code. It was simple, easy to use, and had a nice UI. But it was also slow, and the UI was a bit clunky. It was also a bit of a pain to use in a CI environment - unfortunatly the site has gone down, and while there exist alternatives that perform the same function, what's stopping them from also going down?
Enter Benchmark.js
JSPerf - and I'd wager a good number of the alternatives - use Benchmark.js under the hood. Benchmark.js is a library that allows you to benchmark JavaScript code, handling the timer accuracy and ensuring that the results aren't skewed by naive approaches to benchmarking.
Comparative Benchmarking
A common approach to benchmarking is to compare the performance of two different implementations of the same function, not only does this - as the name suggests - reveal which implementation is faster, but it also allows you to incrementially make changes to said functions to discover where the performance bottlenecks are.
So instead of manually adding the same case to the Benchmark.js suite, I threw together a helper script that will allow one to compare the results of various functions with the same input:
const bench = require('benchmark');
module.exports = (test, ...functions) => {
const suite = new bench.Suite();
for (const func of functions) {
suite.add(func.name, test.bind(null, func));
}
return suite
.on('start', () => console.log('Starting benchmark...'))
.on('cycle', (event) => {
console.log(String(event.target));
}).on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'));
}).run({ 'async': true });
}
and it can be used by passing first the case to run all with all functions - the current function being passed as the first argument - and then the functions to compare:
require('./bench.js')((func) => {
func('aeiou');
func('123456789');
func('AsDfGhJkL');
}, function reverseString(text) {
return text.split("").reverse().join("");
}, function reverseStringForLoop(text) {
let result = "";
for (let i = text.length - 1; i >= 0; i--) {
result += text[i];
}
return result;
});
which after running outputs:
Starting benchmark...
reverseString x 664,315 ops/sec ±2.93% (80 runs sampled)
reverseStringForLoop x 1,979,351 ops/sec ±1.34% (86 runs sampled)
Fastest is reverseStringForLoop
In the Browser?
For those that long for the days of JSPerf, the browser replacements I would recommand if you don't want to spin up Node.js would be jsbench.me, and to do similar tests as we have here - comparing functions with the same input/output - one only needs to define a test block for each one, and the inputs/outputs for each function in the setup block, or all the information in the setup block and the calls in the test blocks like so: https://jsbench.me/nql96erx5r.
Comparison
Of course this doesn't have the cross-browser comparibility or link-sharability of JSPerf, but not only does it show you the performance where you're actually running the code - as Benchmark.js is a web-compatible library - but your saved benchmark tests also won't disappear all at once if the site goes down.