Grunt task for benchmarking
npm install grunt-benchmarkGrunt task for benchmarking with [Benchmark.js].
npm install grunt-benchmarkThen add this line to your project's Gruntfile:
``javascript`
grunt.loadNpmTasks('grunt-benchmark');
folder and create a benchmark script within that folder,
ie fibonacci.js:`javascript
var fibonacci = function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};module.exports = function() {
fibonacci(10);
};
`Then setup your Gruntfile config to run the benchmarks within the
benchmarks/ folder:`javascript
grunt.initConfig({
benchmark: {
all: {
src: ['benchmarks/*.js'],
dest: 'benchmarks/results.csv'
}
}
});
`Then run the task:
`
$ grunt benchmark
Running "benchmark:all" (benchmark) task
Benchmarking "0" [benchmarks/test-timeout.js] x10...
>> test-timeout x 418,070 ops/sec ±12.73% (46 runs sampled)
`Benchmark name, date, times and per iteration will be logged in a csv format.
$3
You can add test options to pass to Benchmark.js by exporting an object of [test options].
`javascript
module.exports = {
name: 'Timeout (asynchronous)',
maxTime: 2,
defer: true,
onComplete: function() {
console.log('Hooray!');
},
fn: function(deferred) {
setTimeout(function() {
deferred.resolve();
}, 500);
}
};
`Result:
`
$ grunt benchmark
Running "benchmark:singleTest" (benchmark) task
Benchmarking "Timeout (asynchronous)" [benchmarks/singleTest.js]...
Hooray!
>> Timeout (asynchronous) x 2.00 ops/sec ±0.14% (8 runs sampled)
`$3
You can pit implementations against one another by creating a test suite.
`javascript
var fibonacci = function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};var fibonacci_memoized = (function ( ) {
var memo = [0, 1];
var fib = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}());
// A test suite
module.exports = {
name: 'Fibonacci Showdown',
tests: {
'Fibonacci': function() {
fibonacci(10);
fibonacci(5);
},
'Fibonacci2': function() {
fibonacci_memoized(10);
fibonacci_memoized(5);
}
}
};
`Result:
`
$ grunt benchmark
Running "benchmark:fibonacci" (benchmark) task
Benchmarking suite "Fibonacci" [benchmarks/fibonacci.js]...
>> fibonacci x 13,386,628 ops/sec ±8.63% (74 runs sampled)
>> fibonacci_memoized x 30,509,658 ops/sec ±2.10% (89 runs sampled)
Fastest is fibonacci_memoized
`####
exports.tests as an Object:Set
exports.tests to an Object that maps test names to functions and or [Benchmark.js test options].`javascript
module.exports = {
name: 'Timeout Showdown',
tests: {
'Return immediately (synchronous)': function() {
return;
},
'Timeout: 50ms (asynchronous)': {
defer: true,
fn: function(deferred) {
setTimeout(deferred.resolve, 50);
}
},
'Timeout: 100ms (asynchronous)': {
defer: true,
fn: function(done) {
setTimeout(deferred.resolve, 100);
}
}
}
};
`####
exports.tests as an Array:
Set exports.tests to an Array of functions and or [Benchmark.js test options].`javascript
module.exports = {
name: 'Timeout Showdown',
tests: [
{
name: 'Return immediately (synchronous)',
fn: function() {
return;
}
},
{
name: 'Timeout: 50ms (asynchronous)',
defer: true,
fn: function(done) {
setTimeout(done, 50);
}
},
{
name: 'Timeout: 100ms (asynchronous)',
defer: true,
fn: function(done) {
setTimeout(done, 100);
}
}
]
};
`
$3
Included is a helper, spawnTask, for running Grunt tasks within your
benchmarks. This example will create a function to run the watch task:`javascript
// benchmarks/watch.js
// Create a spawnable watch task. Doesn't actually spawn until called.
var watchTask = require('grunt-benchmark').spawnTask('watch', { // Text trigger to look for to know when to run the next step or exit
trigger: 'Waiting...',
// Base folder and Gruntfile
// You'll want to setup a fixture base folder and Gruntfile.js
// to ensure your Grunt'ing appropriately
base: 'path/to/a/gruntfile-base',
gruntfile: 'path/to/a/Gruntfile.js'
// Additional Grunt options can be specified here
});
// Our actual benchmark
module.exports = function(done) {
// start the watch task
watchTask([function() {
// After trigger found, run this sync function
// this will trigger the watch task
grunt.file.write('path/to/file.js', 'var test = false;');
}, function() {
// After the previous funciton has ran and another trigger hit...
// run this next sync function
grunt.file.delete('path/to/file.js');
}], function(result) {
// All done, do something more with the output result or finish up the benchmark
done();
});
};
`$3
Test results will be saved to a file if a destination file is provided.`javascript
grunt.initConfig({
benchmark: {
singleTest: {
src: ['benchmarks/fibonacci.js'],
dest: 'results/fibonacci.csv'
}
}
});
`Results can be saved as 'csv' or 'json'. The format is determined from the
dest file extension or by setting the format option:`javascript
grunt.initConfig({
benchmark: {
singleTest: {
src: ['benchmarks/fibonacci.js'],
dest: 'results/fibonacci.txt',
options : {
format: 'csv'
}
}
}
});
`You can specify a truthy
displayResults option inside your Grunt config to
display the results using cli-table.It will automatically pick up the
dest property, so that must be set for this
to work.`javascript
grunt.initConfig({
benchmark: {
options: {
// This can also be set inside specific tests.
displayResults: true
}, singleTest: {
src: ['benchmarks/fibonacci.js'],
dest: 'results/fibonacci.csv'
}
}
});
`The output will look something like:
`bash
Running "benchmark:fibonacci" (benchmark) taskRunning suite Fibonacci [benchmarks/fibonacci.js]...
>> fibonacci x 13,386,628 ops/sec ±8.63% (74 runs sampled)
>> fibonacci_memoized x 30,509,658 ops/sec ±2.10% (89 runs sampled)
Results:
┌──────────────────────┬───────────────────────────────────────────┬───────┬─────────┬────────┬────────────────────┐
│ name │ date │ error │ count │ cycles │ hz │
├──────────────────────┼───────────────────────────────────────────┼───────┼─────────┼────────┼────────────────────┤
│ "fibonacci" │ "Tue Apr 23 2013 21:25:49 GMT-0700 (PDT)" │ │ 906237 │ 4 │ 15154635.038364386 │
├──────────────────────┼───────────────────────────────────────────┼───────┼─────────┼────────┼────────────────────┤
│ "fibonacci_memoized" │ "Fri May 24 2013 19:52:02 GMT-0400 (EDT)" │ │ 1804104 │ 4 │ 31131880.83560733 │
├──────────────────────┼───────────────────────────────────────────┼───────┼─────────┼────────┼────────────────────┤
│ "fibonacci" │ "Tue Apr 23 2013 22:10:55 GMT-0700 (PDT)" │ │ 910791 │ 4 │ 13386627.749339204 │
├──────────────────────┼───────────────────────────────────────────┼───────┼─────────┼────────┼────────────────────┤
│ "fibonacci_memoized" │ "Fri May 24 2013 19:52:11 GMT-0400 (EDT)" │ │ 1764921 │ 4 │ 30509657.596336514 │
└──────────────────────┴───────────────────────────────────────────┴───────┴─────────┴────────┴────────────────────┘
``[grunt]: https://github.com/gruntjs/grunt
[getting_started]: https://gruntjs.com/getting-started
[Benchmark.js]: http://benchmarkjs.com/
[task options]: http://benchmarkjs.com/docs#options