diff options
| author | grothedev <grothedev@gmail.com> | 2026-05-29 21:34:16 -0400 |
|---|---|---|
| committer | grothedev <grothedev@gmail.com> | 2026-05-29 21:34:16 -0400 |
| commit | 27dc5849c3eaf4824d79938e7077abdbe2c82e24 (patch) | |
| tree | 4a6e963d291132ad6f5a22841ea2404b60949366 /web-timeplot/src/metrics.js | |
| parent | 73d75835e18a33c7f6c1b09bbcef93b16a7a9bfa (diff) | |
updates from claude. need to review. archiving rust and cpp stuff, going completely TS
Diffstat (limited to 'web-timeplot/src/metrics.js')
| -rw-r--r-- | web-timeplot/src/metrics.js | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/web-timeplot/src/metrics.js b/web-timeplot/src/metrics.js new file mode 100644 index 0000000..fdda10a --- /dev/null +++ b/web-timeplot/src/metrics.js @@ -0,0 +1,142 @@ +/** + * RollingAverage - Maintains a rolling window of values for smooth averaging + */ +class RollingAverage { + constructor(capacity) { + this.values = []; + this.capacity = capacity; + this.sum = 0; + } + + push(value) { + if (this.values.length >= this.capacity) { + const old = this.values.shift(); + this.sum -= old; + } + this.values.push(value); + this.sum += value; + } + + average() { + return this.values.length > 0 ? this.sum / this.values.length : 0; + } + + min() { + return this.values.length > 0 ? Math.min(...this.values) : 0; + } + + max() { + return this.values.length > 0 ? Math.max(...this.values) : 0; + } +} + +/** + * PerformanceMetrics - Tracks and analyzes frame performance + */ +export class PerformanceMetrics { + constructor(rollingWindow = 60, historyCapacity = 10000) { + // Rolling averages + this.frameTime = new RollingAverage(rollingWindow); + this.updateTime = new RollingAverage(rollingWindow); + this.renderTime = new RollingAverage(rollingWindow); + this.vertexCount = new RollingAverage(rollingWindow); + this.lineCount = new RollingAverage(rollingWindow); + + // History for export + this.history = []; + this.historyCapacity = historyCapacity; + + // Frame timing + this.frameStart = 0; + this.updateStart = 0; + this.renderStart = 0; + + this.totalFrames = 0; + } + + beginFrame() { + this.frameStart = performance.now(); + } + + beginUpdate() { + this.updateStart = performance.now(); + } + + endUpdate() { + const duration = performance.now() - this.updateStart; + return duration; + } + + beginRender() { + this.renderStart = performance.now(); + } + + endRender() { + const duration = performance.now() - this.renderStart; + return duration; + } + + endFrame(updateMs, renderMs, vertexCount, lineCount) { + const totalMs = performance.now() - this.frameStart; + + // Update rolling averages + this.frameTime.push(totalMs); + this.updateTime.push(updateMs); + this.renderTime.push(renderMs); + this.vertexCount.push(vertexCount); + this.lineCount.push(lineCount); + + // Store in history + const record = { + frame: this.totalFrames, + totalMs, + updateMs, + renderMs, + vertexCount, + lineCount, + fps: totalMs > 0 ? 1000 / totalMs : 0, + }; + + if (this.history.length >= this.historyCapacity) { + this.history.shift(); + } + this.history.push(record); + + this.totalFrames++; + } + + getFPS() { + const avg = this.frameTime.average(); + return avg > 0 ? 1000 / avg : 0; + } + + getMinFPS() { + const max = this.frameTime.max(); + return max > 0 ? 1000 / max : 0; + } + + getMaxFPS() { + const min = this.frameTime.min(); + return min > 0 ? 1000 / min : 0; + } + + formatSummary() { + return `FPS: ${this.getFPS().toFixed(1)} (min: ${this.getMinFPS().toFixed(1)}, max: ${this.getMaxFPS().toFixed(1)}) | ` + + `Frame: ${this.frameTime.average().toFixed(2)}ms | ` + + `Update: ${this.updateTime.average().toFixed(2)}ms | ` + + `Render: ${this.renderTime.average().toFixed(2)}ms | ` + + `Vertices: ${Math.round(this.vertexCount.average())} | ` + + `Lines: ${Math.round(this.lineCount.average())}`; + } + + exportToCSV() { + let csv = 'frame,total_ms,update_ms,render_ms,vertex_count,line_count,fps\n'; + + for (const record of this.history) { + csv += `${record.frame},${record.totalMs},${record.updateMs},${record.renderMs},` + + `${record.vertexCount},${record.lineCount},${record.fps}\n`; + } + + return csv; + } +} |
