From 441e0bd9176649169d6d5b931426b0852e0fb611 Mon Sep 17 00:00:00 2001 From: Olivia Casadei Date: Tue, 29 Sep 2026 08:55:48 +0200 Subject: [PATCH] Known issue: stream frames grow browser memory (noted from camera-sensing R11) Co-Authored-By: Claude Opus 5.5 --- KNOWN_ISSUE_stream_memory.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 KNOWN_ISSUE_stream_memory.md diff --git a/KNOWN_ISSUE_stream_memory.md b/KNOWN_ISSUE_stream_memory.md new file mode 100644 index 0000000..3e26cc7 --- /dev/null +++ b/KNOWN_ISSUE_stream_memory.md @@ -0,0 +1,33 @@ +# Known issue: stream frames make browser memory grow + +**Status: not fixed yet** — noted on Olivia's request, 2026-09-29 (camera-sensing R13). No code was changed in this repo. + +## The defect +For **every frame**, the GUI builds a `new Image()` from a `data:image/...;base64,...` URL and reassigns the canvas +`width`/`height`. Left open, the page's memory keeps growing: on 2026-09-28 hostpc (32 GB) ran out of RAM and the +kernel killed a Firefox process holding ~19.8 GB of shared memory, with several camera GUIs open. + +## Where, in this repo +- `src/frontend/react/src/components/StreamView.jsx` — the `useEffect` on `frame` (RGB JPEG or depth PNG): `new Image()` + per frame, canvas resized per frame, then detections / the measurement marker drawn on top. +- `src/frontend/react/src/components/DepthView.jsx` — same pattern for the depth colormap (JPEG) or depth PNG. + +When applying the fix to `StreamView.jsx`, keep drawing the detections and the marker **after** `drawImage`, and +pass the MIME type (`image/jpeg` for RGB, `image/png` for depth) to the `Blob`. + +**The running copy of this service is on PC2**, not on this PC: fixing this local copy does not fix the GUI in use +until it is deployed there. + +## The fix (same as multi-camera_service, commit `dfa0fec`) +1. Decode with `createImageBitmap`: base64 -> `Uint8Array` -> `Blob` -> `createImageBitmap(blob)`, then `drawImage(bitmap, 0, 0)`. +2. Call `bitmap.close()` **right after** drawing (also on error). +3. Resize the canvas **only when the frame size changes** (`if (canvas.width !== bmp.width || ...)`). +4. **Drop** a frame that arrives while the previous one is still decoding (a `decoding` flag, no queue). + +Reference implementation (a React hook, 40 lines): `/opt/docker/sensing/multi-camera_service/src/frontend/react/src/hooks/useJpegCanvas.js`. + +## Measured (multi-camera_service, camera-sensing R11, 2026-09-28) +Headless Chromium, roof stream 1920x1080 at ~15 fps: renderer memory **+838 MB between minute 1 and minute 5** +with the old code; **+5 MB between minute 1 and minute 10** with the fix (+17 MB with a second, 640x480 stream). +Probe: `/opt/docker/sensing/multi-camera_service/scripts/gui_memprobe.py` — it kills the browser above 2 GB of +renderer memory or below 6 GB of system MemAvailable; keep that cap when measuring on hostpc.