audit(19-01): VU meter components memory leak audit

- Audited SessionTrackVU.js, useMixerStore.js, useVuHelpers.js
- Found VUMTR-01: VU callback throttling disabled (MEDIUM)
- Found VUMTR-02: vuStates object grows unbounded (HIGH)
- Found VUMTR-03: No per-mixer cleanup on track leave (HIGH)
- Documented all timer/callback patterns with line numbers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nuwan 2026-02-08 14:16:33 +05:30
parent c466a72511
commit 1c898ddc0b
1 changed files with 119 additions and 0 deletions

View File

@ -0,0 +1,119 @@
# Phase 19: Memory Leak Audit Report
**Audit Date:** 2026-02-08
**Auditor:** Claude Code
**Target:** Session screen memory leak causing ~10-minute freeze
**Methodology:** Static code analysis with line-by-line verification
## Executive Summary
This audit systematically examined the jam-ui session screen components, hooks, and Redux slices to identify memory leak patterns. Each file was analyzed for:
- Timer/interval creation without cleanup
- Event listener registration without removal
- Unbounded state growth patterns
- Callback registration without unregistration
Findings are categorized by severity:
- **HIGH**: Likely contributor to the 10-minute freeze
- **MEDIUM**: May contribute to memory degradation over time
- **LOW**: Minor or properly handled, included for completeness
---
## VU Meter Audit
**Files Audited:**
- `jam-ui/src/components/client/SessionTrackVU.js`
- `jam-ui/src/hooks/useMixerStore.js`
- `jam-ui/src/hooks/useVuHelpers.js`
- `jam-ui/src/hooks/useMixerHelper.js`
- `jam-ui/src/context/VuContext.js`
- `jam-ui/src/context/MixersContext.js`
**Requirements Coverage:** VUMTR-01, VUMTR-02, VUMTR-03
### SessionTrackVU.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 9-30 | useEffect | Mixer registration and VU state updates | YES | LOW | Cleanup resets VU state to 0 and nulls mixerIdRef on unmount |
**Analysis:** This component has proper cleanup. The useEffect at line 9 returns a cleanup function at lines 23-28 that resets the VU state.
### useMixerStore.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 74-94 | useEffect | Sets `window.JK.HandleBridgeCallback2` global callback | YES | LOW | Properly deletes callback on cleanup (line 87) |
| 55 | useRef | `recheckTimeoutRef` for timeout tracking | YES | LOW | Cleared at lines 91 and 205 |
| 135-191 | handleBridgeCallback | VU data processing callback | N/A | MEDIUM | Callback uses ref to avoid stale closure, but could accumulate calls if not throttled |
**Analysis:** The VU callback registration pattern is sound. The `window.JK.HandleBridgeCallback2` is set at line 79 and deleted at line 87 in the cleanup function. The `recheckTimeoutRef` is properly cleared on cleanup.
**Potential Issue (VUMTR-01):** The `handleBridgeCallback` (lines 135-191) processes VU data but has commented-out throttling logic (lines 141-152). Without throttling, this callback may fire at very high rates (native client sends VU data frequently), potentially causing performance degradation over time.
### useVuHelpers.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 6 | useState | `vuStates` object tracking VU levels per mixer | PARTIAL | HIGH | Cleared on unmount but entries never removed during session |
| 99-104 | updateVuState | Updates vuStates object | N/A | HIGH | Adds new keys but never removes old ones |
| 117-122 | useEffect | Cleanup effect | YES | PARTIAL | Only clears entire object on unmount, not per-mixer cleanup |
**Analysis:**
**VUMTR-02 - CRITICAL FINDING:** The `vuStates` object at line 6 accumulates entries over time:
```javascript
const [vuStates, setVuStates] = useState({}); // Line 6
const updateVuState = useCallback((mixerId, level, clipping = false) => {
setVuStates(prev => ({
...prev,
[mixerId]: { level, clipping } // Adds new keys, never removes
}));
}, []); // Lines 99-104
```
When tracks are added/removed during a session, the `vuStates` object grows but entries for removed tracks are never deleted. Over a 10-minute session with multiple track changes, this could accumulate hundreds of stale entries.
**Evidence:**
- Line 100: `setVuStates(prev => ({ ...prev, [mixerId]: { level, clipping } }))` - spreads existing state and adds new entry
- Line 120: `setVuStates({})` - only clears on full unmount
- No mechanism to remove individual mixer entries when tracks leave
### useMixerHelper.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 67 | useRef | `allMixersRef` for mixer tracking | N/A | LOW | Ref, not timer |
| 68 | useRef | `previousMyTracksRef` for track caching | N/A | LOW | Prevents unnecessary re-renders |
| 120 | useRef | `isReady` flag | N/A | LOW | Simple flag ref |
**Analysis:** No timer/interval patterns found. Uses refs appropriately for state that shouldn't trigger re-renders.
### VuContext.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 6-14 | VuProvider | Context provider using useVuHelpers | N/A | N/A | Delegates to useVuHelpers |
**Analysis:** Simple context wrapper. All VU logic is in useVuHelpers.
### MixersContext.js
| Line | Pattern | Description | Has Cleanup | Severity | Notes |
|------|---------|-------------|-------------|----------|-------|
| 6-14 | MixersProvider | Context provider using useMixerHelper | N/A | N/A | Delegates to useMixerHelper |
**Analysis:** Simple context wrapper. All mixer logic is in useMixerHelper.
### VU Meter Findings Summary
| ID | Finding | File | Lines | Severity | Fix Recommendation |
|----|---------|------|-------|----------|-------------------|
| VUMTR-01 | VU callback throttling disabled | useMixerStore.js | 141-152 | MEDIUM | Re-enable or implement proper throttling |
| VUMTR-02 | vuStates object grows unbounded | useVuHelpers.js | 6, 99-104 | HIGH | Add cleanup function to remove stale mixer entries |
| VUMTR-03 | No per-mixer cleanup on track leave | useVuHelpers.js | 117-122 | HIGH | Expose removeVuState function for track cleanup |
---