Skip to content

fix(rrweb): use FNV-1a hash for canvas frame dedup instead of full base64#140

Merged
TueHaulund merged 1 commit intomainfrom
fix/canvas-worker-hash-dedup
Mar 4, 2026
Merged

fix(rrweb): use FNV-1a hash for canvas frame dedup instead of full base64#140
TueHaulund merged 1 commit intomainfrom
fix/canvas-worker-hash-dedup

Conversation

@TueHaulund
Copy link
Contributor

@TueHaulund TueHaulund commented Mar 4, 2026

Summary

  • Replace lastBlobMap: Map<number, string> (storing full ~400KB base64 strings per canvas) with lastFingerprintMap: Map<number, string> (storing 8-char FNV-1a hex digests)
  • For unchanged frames, skip the expensive encode(arrayBuffer) call entirely — hash comparison is done on the raw ArrayBuffer bytes
  • Reduces worker memory per canvas from ~400KB to 8 bytes
  • Eliminates ~400KB of temporary string allocations per unchanged frame
  • FNV-1a is synchronous and works in all contexts (no crypto.subtle / secure context requirement)

Context: investigating ~0.5MB/s memory growth in Safari with session recording enabled on canvas-heavy apps (PostHog/posthog-flutter#306). The canvas capture pipeline creates ~2-3MB of temporary allocations per frame at 2 FPS, overwhelming Safari's GC in Web Workers.

Test plan

  • Verify canvas recording still works (changed frames are captured correctly)
  • Verify unchanged frames are still deduplicated (no redundant data sent)
  • Verify transparent canvas detection still works on first frame
  • Memory profile in Safari to confirm reduced allocation pressure

@TueHaulund TueHaulund requested review from a team, fasyy612, ksvat and pauldambra and removed request for a team March 4, 2026 16:49
@TueHaulund TueHaulund marked this pull request as ready for review March 4, 2026 16:50
…se64

Replace lastBlobMap (storing ~400KB base64 strings per canvas) with
lastFingerprintMap (storing 8-char FNV-1a hex digests). For unchanged
frames, skip the expensive encode(arrayBuffer) call entirely.

This reduces worker memory per canvas from ~400KB to 8 bytes and
eliminates ~400KB of temporary string allocations per unchanged frame,
which helps Safari's GC keep up in high-frequency canvas capture
scenarios.
@TueHaulund TueHaulund force-pushed the fix/canvas-worker-hash-dedup branch from f3ed884 to 43080f4 Compare March 4, 2026 17:36
@TueHaulund TueHaulund changed the title fix(rrweb): use SHA-256 hash for canvas frame dedup instead of full base64 fix(rrweb): use FNV-1a hash for canvas frame dedup instead of full base64 Mar 4, 2026
@TueHaulund TueHaulund merged commit 188a785 into main Mar 4, 2026
8 checks passed
@TueHaulund TueHaulund deleted the fix/canvas-worker-hash-dedup branch March 4, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants