Skip to content

Instantly share code, notes, and snippets.

@dashed
Last active August 29, 2015 14:05
Show Gist options
  • Save dashed/77ee677c46879d2919eb to your computer and use it in GitHub Desktop.
Save dashed/77ee677c46879d2919eb to your computer and use it in GitHub Desktop.
"use strict";
/**
* Deps:
* npm install benchmark EventEmitter3
*/
var EventEmitter = require('events').EventEmitter;
var bus = new EventEmitter();
function nextTick(callback) {
// setTimeout(callback, 0);
callback();
};
function getOptmizationStatus(fn) {
switch(%GetOptimizationStatus(fn)) {
case 1: return("Function is optimized"); break;
case 2: return("Function is not optimized"); break;
case 3: return("Function is always optimized"); break;
case 4: return("Function is never optimized"); break;
case 6: return("Function is maybe deoptimized"); break;
}
};
/**
*
* Test functions
*/
var slice = [].slice;
var preEmit = function() {};
var shouldEmit = function() {return true};
function original() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
bus.emit('action', arguments);
}
};
function originalBind() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
bus.emit.bind(bus, 'action').apply(bus, arguments);
}
};
var emit = bus.emit.bind(bus, 'action');
function originalApply() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
emit.apply(emit, arguments);
}
};
function sliceArr() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = [].slice.call(arguments);
args.unshift('action');
bus.emit.apply(bus, args);
}
};
function arrayApply() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
args.unshift('action');
bus.emit.apply(bus, args);
}
};
function manualMap() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var i = arguments.length;
var args = new Array(i);
while (i-- > 0) args[i] = arguments[i];
args.unshift('action');
bus.emit.apply(bus, args);
}
};
function manualMap2() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var l = arguments.length + 1;
var args = new Array(l);
args[0] = 'action';
while (--l > 0) args[l] = arguments[l - 1];
bus.emit.apply(bus, args);
}
};
function toArray() {
var i = arguments.length;
var args = new Array(i);
while (i-- > 0) args[i] = arguments[i];
return args;
}
function utilToArray() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = toArray.apply(null, arguments);
args.unshift('action');
bus.emit.apply(bus, args);
}
};
function toArray2() {
var l = arguments.length + 1;
var args = new Array(l);
args[0] = this + '';
while (--l > 0) args[l] = arguments[l - 1];
return args;
}
function utilToArray2() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = toArray2.apply('action', arguments);
bus.emit.apply(bus, args);
}
};
function toArray3() {
var end = +(this instanceof String);
var l = arguments.length + end;
var args = new Array(l);
while (l-- > end) {
args[l] = arguments[l - end];
}
if(end) {
args[0] = this + '';
}
return args;
}
function utilToArray3() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = toArray3.apply('action', arguments);
bus.emit.apply(bus, args);
}
};
function toArray4() {
var n = !(this instanceof Number) ? 0 : +(this);
var m = arguments.length + n;
var args = new Array(m);
while (m-- > n) {
args[m] = arguments[m - n];
}
return args;
}
function utilToArray4() {
preEmit.apply(null, arguments);
if (shouldEmit.apply(null, arguments)) {
var args = toArray4.apply(1, arguments);
args[0] = 'action';
bus.emit.apply(bus, args);
}
};
/**
* Set up test cases
*/
var tests = [];
tests.push(original);
tests.push(originalBind);
tests.push(originalApply);
tests.push(sliceArr);
tests.push(arrayApply);
tests.push(manualMap);
tests.push(manualMap2);
tests.push(utilToArray);
tests.push(utilToArray2);
tests.push(utilToArray3);
tests.push(utilToArray4);
//
// Optimize check
//
tests.forEach(function(fn) {
fn();
fn();
fn();
%OptimizeFunctionOnNextCall(fn);
fn();
console.log("STATUS OF " + fn.name + ": " + getOptmizationStatus(fn));
});
console.log();
// benchmark
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
tests.forEach(function(fn) {
suite.add(fn.name, function() {
fn(Math.random());
fn(Math.random(), Math.random());
});
});
suite
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('\nFastest is ' + this.filter('fastest').pluck('name'));
})
.run();
/*
$ node --allow-natives-syntax bench.js
STATUS OF original: Function is not optimized
STATUS OF originalBind: Function is not optimized
STATUS OF originalApply: Function is optimized
STATUS OF sliceArr: Function is not optimized
STATUS OF arrayApply: Function is optimized
STATUS OF manualMap: Function is optimized
STATUS OF manualMap2: Function is optimized
STATUS OF utilToArray: Function is optimized
original x 625,140 ops/sec ±5.77% (83 runs sampled)
originalBind x 29,168 ops/sec ±2.93% (88 runs sampled)
originalApply x 462,980 ops/sec ±1.24% (93 runs sampled)
sliceArr x 133,581 ops/sec ±2.18% (93 runs sampled)
arrayApply x 508,100 ops/sec ±5.28% (85 runs sampled)
manualMap x 527,373 ops/sec ±5.60% (88 runs sampled)
manualMap2 x 678,867 ops/sec ±7.56% (77 runs sampled)
utilToArray x 536,525 ops/sec ±5.56% (93 runs sampled)
Fastest is manualMap2
*/
"use strict";
/**
* Deps:
* npm install benchmark EventEmitter3
*/
var EventEmitter = require('events').EventEmitter;
var bus = new EventEmitter();
function nextTick(callback) {
// setTimeout(callback, 0);
callback();
};
function getOptmizationStatus(fn) {
switch(%GetOptimizationStatus(fn)) {
case 1: return("Function is optimized"); break;
case 2: return("Function is not optimized"); break;
case 3: return("Function is always optimized"); break;
case 4: return("Function is never optimized"); break;
case 6: return("Function is maybe deoptimized"); break;
}
};
/**
*
* Test functions
*/
var slice = [].slice;
var preEmit = function() {};
var shouldEmit = function() {return true};
function original() {
nextTick(function(){
var args = arguments;
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
bus.emit('action', args);
}
}
}.apply(this, arguments));
};
function originalBind() {
nextTick(function(){
var args = arguments;
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
bus.emit.bind(bus, 'action').apply(bus, args);
}
}
}.apply(this, arguments));
};
var emit = bus.emit.bind(bus, 'action');
function originalApply() {
nextTick(function(){
var args = arguments;
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
emit.apply(emit, args);
}
}
}.apply(this, arguments));
};
function sliceArr() {
nextTick(function(){
var args = [].slice.call(arguments);
args.unshift('action');
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
bus.emit.apply(bus, args);
}
}
}.apply(this, arguments));
};
function arrayApply() {
nextTick(function(){
var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
emit.apply(bus, args);
}
}
}.apply(this, arguments));
};
function manualMap() {
var l = arguments.length
var args = new Array(l)
for (var i = 0; i < l; i ++) args[i] = arguments[i]
args.unshift('action');
nextTick(function(){
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
bus.emit.apply(bus, args);
}
});
};
function manualMap2() {
nextTick(function(){
var l = arguments.length
var args = new Array(l + 1)
args[0] = 'action'
for (var i = 1; i <= l; i ++) args[i] = arguments[i]
return function() {
preEmit.apply(null, args);
if (shouldEmit.apply(null, args)) {
bus.emit.apply(bus, args);
}
}
}.apply(this, arguments));
};
/**
* Set up test cases
*/
var tests = [];
tests.push(original);
tests.push(originalBind);
tests.push(originalApply);
tests.push(sliceArr);
tests.push(arrayApply);
tests.push(manualMap);
tests.push(manualMap2);
//
// Optimize check
//
tests.forEach(function(fn) {
fn();
fn();
fn();
%OptimizeFunctionOnNextCall(fn);
fn();
console.log("STATUS OF " + fn.name + ": " + getOptmizationStatus(fn));
});
console.log();
// benchmark
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
tests.forEach(function(fn) {
suite.add(fn.name, function() {
fn(Math.random());
fn(Math.random(), fn(Math.random()));
});
});
suite
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('\nFastest is ' + this.filter('fastest').pluck('name'));
})
.run();
/*
$ node --allow-natives-syntax bench.js
STATUS OF original: Function is optimized
STATUS OF originalBind: Function is optimized
STATUS OF originalApply: Function is optimized
STATUS OF sliceArr: Function is optimized
STATUS OF arrayApply: Function is optimized
STATUS OF manualMap: Function is optimized
STATUS OF manualMap2: Function is optimized
original x 505,494 ops/sec ±6.06% (84 runs sampled)
originalBind x 24,490 ops/sec ±6.00% (79 runs sampled)
originalApply x 203,581 ops/sec ±6.96% (78 runs sampled)
sliceArr x 69,980 ops/sec ±4.77% (88 runs sampled)
arrayApply x 145,812 ops/sec ±3.57% (92 runs sampled)
manualMap x 332,877 ops/sec ±21.13% (81 runs sampled)
manualMap2 x 274,924 ops/sec ±19.36% (72 runs sampled)
Fastest is original
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment