UNPKG

@caspingus/lt

Version:

A utility library of helpers and extensions useful when working with Learnosity APIs.

89 lines (88 loc) 3.2 kB
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 };