@caspingus/lt
Version:
A utility library of helpers and extensions useful when working with Learnosity APIs.
89 lines (88 loc) • 3.2 kB
JavaScript
import e from "./logger.js";
//#region src/utils/memoryMonitor.js
var t = class {
constructor() {
this.measurements = [], this.isMonitoring = !1, this.timerId = null, this.intervalMs = 5e3, this.baselineMB = null, this.baselineTs = null;
}
startMonitoring(e = 5e3) {
if (!("memory" in performance)) {
console.warn("performance.memory not available");
return;
}
this.intervalMs = e, this.baselineMB = Math.round(performance.memory.usedJSHeapSize / 1048576), this.baselineTs = Date.now(), this.isMonitoring = !0, this.monitorMemory();
}
monitorMemory() {
if (!this.isMonitoring) return;
let e = {
used: performance.memory.usedJSHeapSize,
total: performance.memory.totalJSHeapSize,
limit: performance.memory.jsHeapSizeLimit,
timestamp: Date.now()
};
this.measurements.push(e), this.measurements.length > 100 && this.measurements.shift(), this.detectMemoryLeaks(), this.timerId = setTimeout(() => this.monitorMemory(), this.intervalMs);
}
stopMonitoring() {
this.isMonitoring = !1, this.timerId &&= (clearTimeout(this.timerId), null);
}
detectMemoryLeaks(t = 10, n = 1e3) {
if (this.measurements.length < t) return !1;
let r = this.measurements.slice(-t), i = r[r.length - 1].used - r[0].used, a = i / (t * this.intervalMs) * 1e3;
return a > n ? (e.warn("⚠️ Potential memory leak detected:", {
growthMB: (i / 1048576).toFixed(2),
rateBps: a.toFixed(2)
}), this.printReport(Math.min(20, this.measurements.length)), !0) : !1;
}
analyzeMemoryPattern(e = 20) {
let t = this.measurements.slice(-e).map((e) => ({
usedMB: Math.round(e.used / 1048576),
ts: e.timestamp
}));
return {
pattern: t,
stats: this.#e(t)
};
}
printReport(t = 20) {
let { pattern: n, stats: r } = this.analyzeMemoryPattern(t);
if (console.table(n.map((e) => ({
time: new Date(e.ts).toLocaleTimeString(),
usedMB: e.usedMB
}))), this.baselineMB != null && n.length) {
let t = n.at(-1).usedMB - this.baselineMB, r = this.baselineTs ? new Date(this.baselineTs).toLocaleTimeString() : "baseline";
e.log(`Approx delta since baseline (${r}): ${t.toFixed(1)} MB`);
}
return e.log("Memory stats:", r), {
pattern: n,
stats: r
};
}
#e(e) {
if (!e.length) return null;
let t = e.map((e) => e.usedMB), n = Math.min(...t), r = Math.max(...t), i = +(t.reduce((e, t) => e + t, 0) / t.length).toFixed(2), a = e[0].ts, o = e.map((e) => (e.ts - a) / 6e4), { slope: s, r2: c } = this.#t(o, t);
return {
count: e.length,
minMB: n,
maxMB: r,
avgMB: i,
slopeMBperMin: +s.toFixed(3),
r2: +c.toFixed(3),
leakSuspect: s > .5 && c > .6
};
}
#t(e, t) {
let n = e.length;
if (n < 2) return {
slope: 0,
intercept: t[0] ?? 0,
r2: 0
};
let r = e.reduce((e, t) => e + t, 0), i = t.reduce((e, t) => e + t, 0), a = e.reduce((e, n, r) => e + n * t[r], 0), o = e.reduce((e, t) => e + t * t, 0), s = r / n, c = i / n, l = a - n * s * c, u = o - n * s * s, d = u ? l / u : 0, f = c - d * s, p = t.reduce((e, t) => e + (t - c) ** 2, 0), m = t.reduce((t, n, r) => t + (n - (d * e[r] + f)) ** 2, 0);
return {
slope: d,
intercept: f,
r2: p ? 1 - m / p : 0
};
}
};
//#endregion
export { t as default };