Files
carto-4.2.2-1.js/src/core/profiler.js
T
2024-05-23 15:34:45 +08:00

161 lines
3.1 KiB
JavaScript

/*
# 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;