Function.prototype.bench = function(update){ update = update || alert; var self = this; var start, end; return this. addBefore(function(){start = new Date}). addAfter (function(){end = new Date;update(end - start)}) } function Profiler(){ this.keys = []; this.records = {}; } Profiler.prototype = { observe : function(object,name){ var prof = this; object.each(function(f,method){ if(typeof f != "function") return; var key = name +"::"+ method; prof.keys.push(key); prof.records[key] = []; object[method] = f.bench(function(time){prof.records[key].push(time)}) }) }, result : function(){ var prof = this; var out = []; prof.keys.forEach(function(key){ var rs = prof.records[key]; if(!rs.length){return} out.push([key ," count:" , rs.length ," total:" , rs.sum() ," mean:" , Math.floor(rs.mean() * 10) / 10 ," max:" , Math.floor(rs.max() * 10) / 10 ," min:" , Math.floor(rs.min() * 10) / 10 ].join("")) }); return out; }, alert: function(){ alert(this.result().join("\n")); } }; Array.prototype.extend({ sum: function(){ for(var i = 0, sum = 0; i < this.length; i++) sum += this[i]; return sum; }, mean: function(){ return (this.length > 0) ? (this.sum() / this.length) : 0; }, max: function(){ return (this.length) ? Math.max.apply(null,this) : 0 }, min: function(){ return (this.length) ? Math.min.apply(null,this) : 0 } })