Created
March 3, 2016 21:33
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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