first commit
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
# metrics profiler
|
||||
|
||||
## timing
|
||||
|
||||
```
|
||||
var timer = Profiler.metric('resource:load')
|
||||
time.start();
|
||||
...
|
||||
time.end();
|
||||
```
|
||||
|
||||
## counters
|
||||
|
||||
```
|
||||
var counter = Profiler.metric('requests')
|
||||
counter.inc(); // 1
|
||||
counter.inc(10); // 11
|
||||
counter.dec() // 10
|
||||
counter.dec(10) // 0
|
||||
```
|
||||
|
||||
## Calls per second
|
||||
```
|
||||
var fps = Profiler.metric('fps')
|
||||
function render() {
|
||||
fps.mark();
|
||||
}
|
||||
```
|
||||
*/
|
||||
var MAX_HISTORY = 1024;
|
||||
function Profiler () {}
|
||||
Profiler.metrics = {};
|
||||
Profiler._backend = null;
|
||||
|
||||
Profiler.get = function (name) {
|
||||
return Profiler.metrics[name] || {
|
||||
max: 0,
|
||||
min: Number.MAX_VALUE,
|
||||
avg: 0,
|
||||
total: 0,
|
||||
count: 0,
|
||||
last: 0,
|
||||
history: typeof (Float32Array) !== 'undefined' ? new Float32Array(MAX_HISTORY) : []
|
||||
};
|
||||
};
|
||||
|
||||
Profiler.backend = function (_) {
|
||||
Profiler._backend = _;
|
||||
};
|
||||
|
||||
Profiler.new_value = function (name, value, type, defer) {
|
||||
type = type || 'i';
|
||||
var t = Profiler.metrics[name] = Profiler.get(name);
|
||||
|
||||
t.max = Math.max(t.max, value);
|
||||
t.min = Math.min(t.min, value);
|
||||
t.total += value;
|
||||
++t.count;
|
||||
t.avg = t.total / t.count;
|
||||
t.history[t.count % MAX_HISTORY] = value;
|
||||
|
||||
if (!defer) {
|
||||
Profiler._backend && Profiler._backend([type, name, value]);
|
||||
} else {
|
||||
var n = performance.now();
|
||||
// don't allow to send stats quick
|
||||
if (n - t.last > 1000) {
|
||||
Profiler._backend && Profiler._backend([type, name, t.avg]);
|
||||
t.last = n;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Profiler.print_stats = function () {
|
||||
for (var k in Profiler.metrics) {
|
||||
var t = Profiler.metrics[k];
|
||||
console.log(' === ' + k + ' === ');
|
||||
console.log(' max: ' + t.max);
|
||||
console.log(' min: ' + t.min);
|
||||
console.log(' avg: ' + t.avg);
|
||||
console.log(' count: ' + t.count);
|
||||
console.log(' total: ' + t.total);
|
||||
}
|
||||
};
|
||||
|
||||
function Metric (name) {
|
||||
this.t0 = null;
|
||||
this.name = name;
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
Metric.prototype = {
|
||||
|
||||
//
|
||||
// start a time measurement
|
||||
//
|
||||
start: function () {
|
||||
this.t0 = performance.now();
|
||||
return this;
|
||||
},
|
||||
|
||||
// elapsed time since start was called
|
||||
_elapsed: function () {
|
||||
return performance.now() - this.t0;
|
||||
},
|
||||
|
||||
//
|
||||
// finish a time measurement and register it
|
||||
// ``start`` should be called first, if not this
|
||||
// function does not take effect
|
||||
//
|
||||
end: function (defer) {
|
||||
if (this.t0 !== null) {
|
||||
Profiler.new_value(this.name, this._elapsed(), 't', defer);
|
||||
this.t0 = null;
|
||||
}
|
||||
},
|
||||
|
||||
//
|
||||
// increments the value
|
||||
// qty: how many, default = 1
|
||||
//
|
||||
inc: function (qty) {
|
||||
qty = qty === undefined ? 1 : qty;
|
||||
Profiler.new_value(this.name, qty, 'i');
|
||||
},
|
||||
|
||||
//
|
||||
// decrements the value
|
||||
// qty: how many, default = 1
|
||||
//
|
||||
dec: function (qty) {
|
||||
qty = qty === undefined ? 1 : qty;
|
||||
Profiler.new_value(this.name, qty, 'd');
|
||||
},
|
||||
|
||||
//
|
||||
// measures how many times per second this function is called
|
||||
//
|
||||
mark: function () {
|
||||
++this.count;
|
||||
if (this.t0 === null) {
|
||||
this.start();
|
||||
return;
|
||||
}
|
||||
var elapsed = this._elapsed();
|
||||
if (elapsed > 1) {
|
||||
Profiler.new_value(this.name, this.count);
|
||||
this.count = 0;
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Profiler.metric = function (name) {
|
||||
return new Metric(name);
|
||||
};
|
||||
|
||||
module.exports = Profiler;
|
||||
Reference in New Issue
Block a user