From 6f5ac3aa5a7173122323ec1a0e43840b27a8d231 Mon Sep 17 00:00:00 2001 From: rUv Date: Sun, 17 May 2026 19:16:00 -0400 Subject: [PATCH] fix(ui): clamp deltaTime to 1ms in pose-renderer FPS calc (#519 Bug 2) (#610) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When two render frames land in the same performance.now() tick, `currentTime - lastFrameTime === 0`, so `fps = 1000 / 0 = Infinity`, and `averageFps = averageFps * 0.9 + Infinity * 0.1 = Infinity` poisons the EMA forever after a single zero-dt tick. The UI then displays "Infinity FPS" until reload. Floor deltaTime at 1 ms before the division. That caps displayed FPS at 1000 (far above any real render rate so the cap is never observed in practice) but keeps the EMA finite. Reported in #519 ("Bug 2 — FPS shows Infinity") by @kapilsoni2013 on a 3-node ESP32-S3-WROOM multi-node setup with edge-tier 1 + 2. --- CHANGELOG.md | 3 +++ ui/utils/pose-renderer.js | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a66d9a39..cbd2a304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- **`ui/utils/pose-renderer.js` no longer divides by zero** when two render frames land in the same `performance.now()` tick (issue #519 Bug 2). `deltaTime` is now `Math.max(currentTime - lastFrameTime, 1)` before the `1000 / deltaTime` division, capping displayed FPS at 1000 — far above any real render rate, but finite so the EMA `averageFps = averageFps * 0.9 + fps * 0.1` no longer poisons itself to `Infinity` on a single zero-dt tick. + ### Removed - **Stub crates `wifi-densepose-api`, `wifi-densepose-db`, `wifi-densepose-config`** (closes #578). Each was a single-line doc-comment placeholder with an empty `[dependencies]` diff --git a/ui/utils/pose-renderer.js b/ui/utils/pose-renderer.js index 644d965c..58540d1e 100644 --- a/ui/utils/pose-renderer.js +++ b/ui/utils/pose-renderer.js @@ -651,14 +651,18 @@ export class PoseRenderer { this.performanceMetrics.frameCount++; if (this.performanceMetrics.lastFrameTime > 0) { - const deltaTime = currentTime - this.performanceMetrics.lastFrameTime; + // Clamp to a minimum dt so consecutive frames within the same + // performance.now() tick don't yield Infinity (issue #519 Bug 2). + // 1 ms floor caps the displayed FPS at 1000 — far above any real + // render rate, but finite so the EMA stays well-defined. + const deltaTime = Math.max(currentTime - this.performanceMetrics.lastFrameTime, 1); const fps = 1000 / deltaTime; - + // Update average FPS using exponential moving average if (this.performanceMetrics.averageFps === 0) { this.performanceMetrics.averageFps = fps; } else { - this.performanceMetrics.averageFps = + this.performanceMetrics.averageFps = (this.performanceMetrics.averageFps * 0.9) + (fps * 0.1); } }