Last active
August 29, 2015 14:05
-
-
Save dashed/77ee677c46879d2919eb to your computer and use it in GitHub Desktop.
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
"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 | |
*/ |
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
"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