discourse/vendor/assets/javascripts/probes.js

177 lines
4.2 KiB
JavaScript
Raw Normal View History

2013-02-26 00:42:20 +08:00
/*
2013-02-06 03:16:51 +08:00
* JavaScript probing framework by Sam Saffron
* MIT license
*
*
2013-02-26 00:42:20 +08:00
* Examples:
*
* someFunction = window.probes.measure(someFunction, {
* name: "somename" // or function(args) { return "name"; },
* before: function(data, owner, args) {
2013-03-11 23:13:28 +08:00
* // if owner is true, we are not in a recursive function call.
* //
2013-03-11 23:13:28 +08:00
* // data contains the bucker of data already measuer
* // data.count >= 0
* // data.time is the total time measured till now
* //
2013-03-11 23:13:28 +08:00
* // arguments contains the original arguments sent to the function
* },
* after: function(data, owner, args) {
* // same format as before
* }
* });
*
*
2013-03-11 23:13:28 +08:00
* // minimal
* someFunction = window.probes.measure(someFunction, "someFunction");
2013-03-11 23:13:28 +08:00
*
2013-02-06 03:16:51 +08:00
* */
(function(){
2013-02-26 00:42:20 +08:00
var measure, clear;
2013-02-06 03:16:51 +08:00
clear = function() {
window.probes = {
clear: clear,
measure: measure,
displayProbes: displayProbes
2013-02-06 03:16:51 +08:00
};
};
measure = function(fn,options) {
// start is outside so we measure time around recursive calls properly
var start = null, nameParam, before, after;
if (!options) {
options = {};
}
if (typeof options === "string") {
nameParam = options;
}
2013-02-26 00:42:20 +08:00
else
2013-02-06 03:16:51 +08:00
{
nameParam = options.name;
2013-02-06 03:16:51 +08:00
if (nameParam === "measure" || nameParam === "clear") {
2013-02-26 00:42:20 +08:00
throw new Error("can not be called measure or clear");
2013-02-06 03:16:51 +08:00
}
2013-02-26 00:42:20 +08:00
2013-02-06 03:16:51 +08:00
if (!nameParam)
{
throw new Error("you must specify the name option measure(fn, {name: 'some name'})");
2013-02-06 03:16:51 +08:00
}
before = options.before;
after = options.after;
2013-02-06 03:16:51 +08:00
}
var now = (function(){
var perf = window.performance || {};
var time = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
return time ? time.bind(perf) : function() { return new Date().getTime(); };
})();
return function() {
var name = nameParam;
if (typeof name === "function"){
2013-02-06 03:16:51 +08:00
name = nameParam(arguments);
}
var p = window.probes[name];
var owner = (!start);
2013-02-26 00:42:20 +08:00
2013-02-06 03:16:51 +08:00
if (before) {
// would like to avoid try catch so its optimised properly by chrome
before(p, owner, arguments);
}
if (p === undefined) {
window.probes[name] = {count: 0, time: 0, currentTime: 0};
p = window.probes[name];
}
var callStart;
if (owner) {
start = now();
callStart = start;
}
2013-03-11 23:13:28 +08:00
else if(after) {
2013-02-06 03:16:51 +08:00
callStart = now();
}
2013-02-26 00:42:20 +08:00
var r = fn.apply(this, arguments);
2013-02-06 03:16:51 +08:00
if (owner && start) {
2013-02-26 00:42:20 +08:00
p.time += now() - start;
2013-02-06 03:16:51 +08:00
start = null;
}
p.count += 1;
if (after) {
p.currentTime = now() - callStart;
// would like to avoid try catch so its optimised properly by chrome
after(p, owner, arguments);
}
return r;
};
};
2013-02-06 03:16:51 +08:00
var displayProbes = function(){
var pre;
var text = "";
var body = document.getElementsByTagName("body")[0];
for(var prop in window.probes){
var probe = window.probes[prop];
if(probe && probe.count){
text += prop + ": " + probe.time + " ( " + probe.count + " )\n";
}
}
pre = document.getElementById("__probes");
if(!body){
return;
}
if(pre){
pre.textContent = text;
pre.innerText = text;
return;
}
var div = document.createElement("div");
div.id = "__probes_wrapper";
div.setAttribute("style", "position: fixed; bottom: 25px; left: 50px; z-index: 99999; border: 1px solid #777; padding: 10px; background-color: rgba(255,255,255, 0.8);");
pre = document.createElement("pre");
pre.setAttribute("style", "margin:0 0 5px;");
pre.textContent = text;
pre.innerText = text;
pre.id = "__probes";
div.appendChild(pre);
var a = document.createElement('a');
a.href = "";
a.innerText = "clear";
a.addEventListener("click", function(e){
for(var prop in window.probes){
var probe = window.probes[prop];
if(probe && probe.count){
delete window.probes[prop];
}
}
displayProbes();
e.preventDefault();
});
div.appendChild(a);
body.appendChild(div);
};
// setInterval(displayProbes, 1000);
2013-02-06 03:16:51 +08:00
clear();
})();