125 lines
3.3 KiB
JavaScript
125 lines
3.3 KiB
JavaScript
const ConsoleLogger = require("./Util/ConsoleLogger");
|
||
const Benchmark = require("./Benchmark");
|
||
const debugBenchmark = require("debug")("Eleventy:Benchmark");
|
||
|
||
class BenchmarkGroup {
|
||
constructor() {
|
||
this.benchmarks = {};
|
||
// Warning: aggregate benchmarks automatically default to false via BenchmarkManager->getBenchmarkGroup
|
||
this.isVerbose = true;
|
||
this.logger = new ConsoleLogger(this.isVerbose);
|
||
this.minimumThresholdMs = 0;
|
||
this.minimumThresholdPercent = 8;
|
||
}
|
||
|
||
setIsVerbose(isVerbose) {
|
||
this.isVerbose = isVerbose;
|
||
this.logger.isVerbose = isVerbose;
|
||
}
|
||
|
||
reset() {
|
||
for (var type in this.benchmarks) {
|
||
this.benchmarks[type].reset();
|
||
}
|
||
}
|
||
|
||
// TODO use addAsync everywhere instead
|
||
add(type, callback) {
|
||
let benchmark = (this.benchmarks[type] = new Benchmark());
|
||
|
||
return function (...args) {
|
||
benchmark.before();
|
||
let ret = callback.call(this, ...args);
|
||
benchmark.after();
|
||
return ret;
|
||
};
|
||
}
|
||
|
||
// callback must return a promise
|
||
// async addAsync(type, callback) {
|
||
// let benchmark = (this.benchmarks[type] = new Benchmark());
|
||
|
||
// benchmark.before();
|
||
// // don’t await here.
|
||
// let promise = callback.call(this);
|
||
// promise.then(function() {
|
||
// benchmark.after();
|
||
// });
|
||
// return promise;
|
||
// }
|
||
|
||
setMinimumThresholdMs(minimumThresholdMs) {
|
||
let val = parseInt(minimumThresholdMs, 10);
|
||
if (isNaN(val)) {
|
||
throw new Error("`setMinimumThresholdMs` expects a number argument.");
|
||
}
|
||
this.minimumThresholdMs = val;
|
||
}
|
||
|
||
setMinimumThresholdPercent(minimumThresholdPercent) {
|
||
let val = parseInt(minimumThresholdPercent, 10);
|
||
if (isNaN(val)) {
|
||
throw new Error(
|
||
"`setMinimumThresholdPercent` expects a number argument."
|
||
);
|
||
}
|
||
this.minimumThresholdPercent = val;
|
||
}
|
||
|
||
has(type) {
|
||
return !!this.benchmarks[type];
|
||
}
|
||
|
||
get(type) {
|
||
if (!this.benchmarks[type]) {
|
||
this.benchmarks[type] = new Benchmark();
|
||
}
|
||
return this.benchmarks[type];
|
||
}
|
||
|
||
padNumber(num, length) {
|
||
if (("" + num).length >= length) {
|
||
return num;
|
||
}
|
||
|
||
let prefix = new Array(length + 1).join(" ");
|
||
return (prefix + num).substr(-1 * length);
|
||
}
|
||
|
||
finish(label, totalTimeSpent) {
|
||
for (var type in this.benchmarks) {
|
||
let bench = this.benchmarks[type];
|
||
let isAbsoluteMinimumComparison = this.minimumThresholdMs > 0;
|
||
let totalForBenchmark = bench.getTotal();
|
||
let percent = Math.round((totalForBenchmark * 100) / totalTimeSpent);
|
||
let callCount = bench.getTimesCalled();
|
||
|
||
let output = {
|
||
ms: this.padNumber(totalForBenchmark.toFixed(0), 6),
|
||
percent: this.padNumber(percent, 3),
|
||
calls: this.padNumber(callCount, 5),
|
||
};
|
||
let str = `Benchmark ${output.ms}ms ${output.percent}% ${output.calls}× (${label}) ${type}`;
|
||
|
||
if (
|
||
(isAbsoluteMinimumComparison &&
|
||
totalForBenchmark >= this.minimumThresholdMs) ||
|
||
percent > this.minimumThresholdPercent
|
||
) {
|
||
this.logger.warn(str);
|
||
}
|
||
|
||
// Opt out of logging if low count (1× or 2×) or 0ms / 1%
|
||
if (
|
||
totalForBenchmark.toFixed(0) > 1 || // more than 1ms
|
||
callCount > 2 || // more than 2×
|
||
percent > 1 // more than 1%
|
||
) {
|
||
debugBenchmark(str);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
module.exports = BenchmarkGroup;
|