Created
September 18, 2010 04:13
-
-
Save lamberta/585344 to your computer and use it in GitHub Desktop.
JavaScript code profiling and stats tools.
This file contains hidden or 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
/* JavaScript code profiling and stats tools. | |
*/ | |
var timer; | |
(function () { | |
/* Stats for function execution. | |
* @param {Function} fn Function to time. | |
* @param {Array} params Arguments to supply to function. | |
* @param {Number} iterations Number of times to execute the given function. | |
* @param {Number} runs Number of runs to calculate stats. | |
* @param {Boolean} silentRun [false] No logging of individual run times to console. | |
* @param {Boolean} silentSummary [false] No logging of summary stats to console. | |
* @param {Boolean} returnObj [false] Return an Object containing stats properties. | |
* @param {Boolean} showALl [false] Show all mode frequencies. | |
* @return {Boolean|Object} True/false on successful runs, or stats Object. | |
*/ | |
timer = function (fn, params, iterations, runs, silentRun, silentSummary, returnObj, showAll) { | |
var total = 0, | |
results = [], | |
counts = {}, | |
mean, min, max, mid, i, n, | |
run_str, iter_str; | |
if (typeof fn !== 'function') { | |
throw new TypeError("timer(*fn*, params, iterations, runs, silent, returnObj, showAll): Parameter must be a function"); | |
} | |
iterations = (iterations === undefined) ? 1 : iterations; | |
runs = (runs === undefined) ? 1 : runs; | |
silentRun = silentRun === true; | |
silentSummary = silentSummary === true; | |
returnObj = returnObj === true; | |
showAll = (showAll === undefined) ? false : showAll; | |
if (!silentRun) { | |
console.log(" Runs | Time"); | |
console.log("--------------"); | |
} | |
for (i=0; i < runs; i++) { | |
total += n = time_fn(fn, params, iterations); | |
results.push(n); | |
if (!silentRun) { | |
console.log(String(' '+(i+1)).slice(-4) +":\t"+ n +" ms."); | |
} | |
} | |
if (!silentSummary) { | |
run_str = (runs > 1) ? " runs, " : " run, "; | |
iter_str = (iterations > 1) ? " iterations" : " iteration"; | |
console.log("--------------"); | |
console.log(runs + run_str + iterations + iter_str +", total time: "+ total +" ms."); | |
} | |
if (runs) { | |
results.sort(function (a, b) { return a - b; }); | |
mean = total/runs; | |
mid = results.length / 2; | |
mid = (mid % 2) ? results[Math.floor(mid)] : (results[mid]+results[mid-1])/2; | |
min = Math.min.apply(null, results); | |
max = Math.max.apply(null, results); | |
if (!silentSummary) { | |
console.log(" Mean (average): "+ mean); | |
console.log(" Median (middle value): "+ mid); | |
console.log(" Mode ("+ (showAll ? "frequencies":"most frequent") +"): "+ calc_mode(results, false, showAll)); | |
console.log(" Range ("+max+" - "+min+"): "+ (max-min)); | |
console.log("--------------"); | |
} | |
if (returnObj) { | |
return { | |
'runs': runs, 'iterations': iterations, 'total': total, | |
'mean': mean, 'median': mid, 'mode': calc_mode(results, true, showAll), | |
'range': {'max': max, 'min': min, 'range': max-min} | |
}; | |
} else { | |
return true; | |
} | |
} else { | |
return false; | |
} | |
} | |
/* Execute a function many times. | |
* @param {Function} fn | |
* @param {Array} params | |
* @param {Number} iterations | |
* @return {Number} Function execution time in milliseconds. | |
*/ | |
function time_fn (fn, params, iterations) { | |
iterations = (iterations === undefined) ? 1 : iterations; | |
params = Array.isArray(params) ? params : [params]; | |
var start, stop; | |
start = new Date().getTime(); | |
while (iterations--) { | |
fn.apply(null, params); | |
}; | |
stop = new Date().getTime(); | |
return (stop - start); | |
} | |
/* Calculate the mode (most frequent value) of a set of numbers. | |
* @param {Array} values | |
* @param {Boolean} returnObj [false] Return result as an Object. | |
* @param {Boolean} showAll Return all frequency information. | |
* @return {String|Object} | |
*/ | |
function calc_mode (values, returnObj, showAll) { | |
var p, max=1, i=values.length, counts={}, modes={}; | |
returnObj = (returnObj === undefined) ? false : returnObj; | |
showAll = (showAll === undefined) ? false : showAll; | |
//tally up frequency | |
while (i--) { | |
p = values[i]; | |
counts[p] = counts.hasOwnProperty(p) ? counts[p]+1 : 1; | |
} | |
//find the mode | |
if (showAll) { | |
modes = counts; | |
} else { | |
for (p in counts) { | |
i = counts[p]; | |
if (i > 1 && i > max) { | |
modes = {}; | |
modes[p] = max = i; | |
} else if (i > 1 && i === max) { | |
modes[p] = i; | |
} | |
} | |
} | |
//output format | |
if (Object.keys(modes).length === 0) { | |
modes = returnObj ? null : "none"; | |
} else { | |
if (!returnObj) { | |
i = ""; | |
for (p in modes) { | |
i += p + ": " + modes[p] + ", "; | |
} | |
modes = i.slice(0, -2); | |
} | |
} | |
return modes; | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment