Skip to content

perf(visualizers): eliminate per-frame allocation and DOM reconstruction #118

Description

@codeacme17

Parent

#114

Summary

Optimize Oscilloscope, Spectrogram, and VU Meter as one real-time visualization pipeline by removing per-frame object allocation, React churn, and SVG node reconstruction.

The current analyzer hooks create transformed object arrays on each frame, after which visualization components perform additional transformations and replace SVG groups or paths. In a production scenario with four active visualizers, this contributed thousands of DOM mutations and consumed a material part of the main-thread frame budget.

Scope

Shared analyzer behavior

  • Integrate the shared real-time scheduling contract.
  • Reuse typed analyzer buffers while analyzer size is unchanged.
  • Avoid converting typed arrays into newly allocated object arrays per frame.
  • Precompute frequency or index coordinates when configuration changes.
  • Separate analyzer sampling from React publication and DOM rendering.
  • Provide a cheap stable path for silence, paused playback, missing analyzers, and unchanged values.

Oscilloscope

  • Reuse a stable rendering layer and path.
  • Keep scales and curve configuration stable until dimensions or relevant props change.
  • Generate path data without allocating an object per sample.
  • Avoid replacing the parent group during audio updates.

Spectrogram

  • Create line, shadow, grid, and axis layers during initialization or structural changes.
  • Reuse line and shadow paths during audio updates.
  • Transform spectrum data once per update.
  • Keep scales stable until dimensions or scale props change.
  • Rebuild grid and axes only when their inputs change.
  • Generate unique gradient and definition identifiers for every instance.

VU Meter

  • Represent the active range as a scalar boundary instead of allocating a binary array for every sample.
  • Avoid traversing and updating every lump when only a small range changed.
  • Keep group context and handlers stable.
  • Preserve mono, stereo, threshold, smoothing, and color behavior.
  • Review transitions that remain continuously active at real-time update rates.

Acceptance criteria

  • Stable playback produces no per-frame child-list mutations in Oscilloscope or Spectrogram.
  • Grid, axis, gradient, and group nodes are not recreated by audio-frame updates.
  • No analyzer creates an object array proportional to sample count on every frame.
  • Each visualizer has at most one live render task per animation frame.
  • Visual publication respects the scheduler's configured maximum rate.
  • Runtime errors, unmount, and hidden-document state stop or suspend work as documented.
  • Multiple visualizer instances do not share conflicting SVG identifiers.
  • Stable VU input produces no React update.
  • A VU update does not allocate a complete binary lump array.
  • Mono and stereo VU output retain their current thresholds and visual behavior.
  • The representative four-visualizer scenario shows a material reduction in mutations and script time.
  • Existing public props and Tone node access remain compatible.

Out of scope

  • Waveform peak generation and rendering.
  • Pointer-driven controls.
  • Package entry-point changes.
  • A full Canvas rewrite unless measurements prove the retained SVG path cannot meet the agreed budget.

Validation

  • Measure each visualizer independently and in the four-instance production scenario.
  • Test silence, active audio, pause, resume, configuration changes, resize, hidden document, error, and unmount.
  • Verify visual output for line, shadow, grids, axes, mono, and stereo configurations.
  • Run multi-instance tests that detect shared SVG identifiers.

Dependencies

Blocked by: #117.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions