Skip to content

Instantly share code, notes, and snippets.

@kadamwhite
Last active July 12, 2016 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kadamwhite/0e3240d7c475a91cb0fbbbc4a084e351 to your computer and use it in GitHub Desktop.
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
<!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