Last active
July 12, 2016 18:54
-
-
Save kadamwhite/0e3240d7c475a91cb0fbbbc4a084e351 to your computer and use it in GitHub Desktop.
A performance test of different method invocation techniques, and the use or non-use of arguments
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
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
</head> | |
<body> | |
<script> | |
var seeded = false; | |
var lcg = (function() { | |
var m = 4294967296,a = 1664525,c = 1013904223,seed, z; | |
return {setSeed:function(val) {z = seed = (val == null ? Math.random() * m : val) >>> 0;}, | |
getSeed:function() {return seed;},rand:function() {z = (a * z + c) % m;return z / m;}};}()); | |
// Current implementation | |
function random(min, max) { | |
var rand; | |
if (seeded) { | |
rand = lcg.rand(); | |
} else { | |
rand = Math.random(); | |
} | |
if (arguments.length === 0) { | |
return rand; | |
} else | |
if (arguments.length === 1) { | |
if (arguments[0] instanceof Array) { | |
return arguments[0][Math.floor(rand * arguments[0].length)]; | |
} else { | |
return rand * min; | |
} | |
} else { | |
if (min > max) { | |
var tmp = min; | |
min = max; | |
max = tmp; | |
} | |
return rand * (max-min) + min; | |
} | |
} | |
// Proposed implementation | |
function randomNoArgs(min, max) { | |
var rand; | |
if (seeded) { | |
rand = lcg.rand(); | |
} else { | |
rand = Math.random(); | |
} | |
if (typeof min === 'undefined') { | |
return rand; | |
} else | |
if (typeof max === 'undefined') { | |
if (min instanceof Array) { | |
return min[Math.floor(rand * min.length)]; | |
} else { | |
return rand * min; | |
} | |
} else { | |
if (min > max) { | |
var tmp = min; | |
min = max; | |
max = tmp; | |
} | |
return rand * (max-min) + min; | |
} | |
} | |
// Test Harness | |
var obj = { | |
random: random, | |
randomNoArgs: randomNoArgs | |
}; | |
function lookup( method ) { | |
return function() { | |
return obj[ method ](); | |
} | |
} | |
var methodsToTest = [ | |
{ method: random, name: 'basic' }, | |
{ method: lookup('random'), name: 'object lookup' }, | |
{ method: random, name: 'bound function' }, | |
{ method: randomNoArgs, name: 'basic without "arguments"' }, | |
{ method: lookup('randomNoArgs'), name: 'object lookup without "arguments"' }, | |
{ method: randomNoArgs, name: 'bound function without "arguments"' } | |
]; | |
var results = methodsToTest.reduce(function( resultsArrs, testCfg ) { | |
resultsArrs[ testCfg.name ] = []; | |
return resultsArrs; | |
}, {}); | |
// Test method | |
function test( method, name ) { | |
var startTime = new Date(); | |
// Un-comment these if you want to see the results stream to console as they come in: | |
// console.time( name ); | |
for (var i = 0; i < 1000000; i++) { | |
method(); | |
} | |
// console.timeEnd( name ); | |
results[ name ].push( endTime = new Date() - startTime ); | |
} | |
// The length of this array determines how many passes will be made for each method | |
var arr = []; | |
for (var i = 0; i < 100; i++) { arr.push(null); } | |
// Reduce over the array and return a promise at each step so tests do not lock browser | |
var allTestsDone = methodsToTest.reduce(function(prom1, testCfg) { | |
return prom1.then(function() { | |
console.log( 'Starting tests for ' + testCfg.name ); | |
return arr.reduce(function(prom) { | |
return prom.then(function() { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
test( testCfg.method, testCfg.name ); | |
resolve(); | |
}, 1); | |
}); | |
}); | |
}, Promise.resolve() ) | |
}); | |
}, Promise.resolve()); | |
allTestsDone | |
.then(function() { | |
Object.keys( results ).forEach(function( key ) { | |
console.log( 'Average runtime for ' + key + ':' ); | |
console.log( (results[ key ].reduce(function( sum, val ) { | |
return sum + val; | |
}, 0 ) / results[key].length).toFixed(2) + 'ms' ) | |
}); | |
}) | |
.catch(function(err) { console.error( err ); }); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment