Skip to content

Instantly share code, notes, and snippets.

@kevinoid
Created March 3, 2016 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinoid/8278d3d27f409932a967 to your computer and use it in GitHub Desktop.
Save kevinoid/8278d3d27f409932a967 to your computer and use it in GitHub Desktop.
An example of how to add timeouts and recover from errors in deferred benchmarks with Benchmark.js.
/**
* An example of how to add timeouts and recover from errors in deferred
* benchmarks with Benchmark.js.
*
* @see https://github.com/bestiejs/benchmark.js/issues/123
* @copyright Copyright 2016 Kevin Locke <kevin@kevinlocke.name>
* @license MIT
*/
'use strict';
/* global currentBenchmarkDeferred */
var Benchmark = require('benchmark');
var assert = require('assert');
var suite = new Benchmark.Suite();
suite
// Errors for non-deferred tests behave correctly without extra effort
.add('throws', 'throw new Error("oops");')
// Errors for deferred tests require extra effort, as shown below
.add('throws defer', {
defer: true,
fn: 'throw new Error("oops");',
// Expose deferred for the current benchmark into the global scope during
// setup so that it can be used during error recovery.
setup: 'currentBenchmarkDeferred = deferred;'
})
// If errors are handled correctly and the suite has not been aborted,
// this benchmark should still run regardless of the above
.add('ok', '"Hello World!".indexOf("o") > -1')
.on('cycle', function(evt) {
console.log(String(evt.target));
})
.on('error', function(evt) {
console.log('error in suite', evt.target.error);
});
var currentBenchmark;
function onBenchmarkError(err) {
// Set the error property of the benchmark, as the internals would do
currentBenchmark.error = err;
// Abort the current benchmark (doesn't abort the suite)
currentBenchmark.abort();
// Call .resolve() to signal this cycle has finished
currentBenchmarkDeferred.resolve();
}
function onBenchmarkTimeout() {
onBenchmarkError(new Error('Timeout'));
}
var currentBenchmarkTimeout;
function onBenchmarkStart() {
// Since error handling relies on global variables and the global error
// handler, benchmarks can not be run concurrently.
// If this is desired, a solution using domains may be possible on Node.
assert(!currentBenchmark, 'concurrent benchmarks are not supported');
currentBenchmark = this;
process.once('uncaughtException', onBenchmarkError);
// Timeout delay depends on cycle duration. Adjust accordingly.
currentBenchmarkTimeout = setTimeout(onBenchmarkTimeout, 10000);
}
function onBenchmarkComplete() {
clearTimeout(currentBenchmarkTimeout);
currentBenchmarkTimeout = null;
process.removeListener('uncaughtException', onBenchmarkError);
currentBenchmark = null;
}
suite.forEach(function(benchmark) {
benchmark.on('start', onBenchmarkStart);
benchmark.on('complete', onBenchmarkComplete);
});
suite.run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment