Skip to content

Instantly share code, notes, and snippets.

@lamberta
Created September 18, 2010 04:13
Show Gist options
  • Save lamberta/585344 to your computer and use it in GitHub Desktop.
Save lamberta/585344 to your computer and use it in GitHub Desktop.
JavaScript code profiling and stats tools.
/* 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