Skip to content

Speed up suppression-region computation during region edits#1793

Merged
BryonLewis merged 7 commits into
mainfrom
perf/suppression-computation
Jul 23, 2026
Merged

Speed up suppression-region computation during region edits#1793
BryonLewis merged 7 commits into
mainfrom
perf/suppression-computation

Conversation

@mattdawkins

Copy link
Copy Markdown
Member

Problem

Resizing a large suppression region (especially one carrying a polygon) on sequences with many detections lagged during the drag and briefly hung when releasing the corner handle.

Three compounding costs:

  1. Every intermediate drag event bumps the pending-save counter, which re-ran the dataset-wide fully-suppressed computation (every keyframe of every track, each doing 16×16 point sampling against the region polygons) once per mouse move.
  2. The per-frame suppressed set was computed three times per update — once each for the canvas (LayerManager), the per-frame type counts (FilterList), and the track list.
  3. Every candidate detection on the frame paid the full point-sampling cost even when it obviously couldn't reach the coverage threshold.

Fix

  • BBox prefilter: getSuppressedTrackIds first computes a cheap bbox-overlap upper bound on the covered fraction; candidates that cannot possibly reach the threshold skip the point sampling entirely.
  • Per-revision memoization: results are cached per store+frame keyed on an edit revision (the pending-save counter), passed by all three consumers — one computation per frame per edit instead of three.
  • Debounced dataset totals: the fully-suppressed set behind the type-list totals recomputes on a 500 ms debounce instead of synchronously per save-counter bump, so corner drags stay responsive and the totals settle right after the drag ends. Suppression-type/camera changes still recompute immediately.

Unit tests cover the prefilter behavior (covered vs. barely-touching vs. distant candidates) and the memoization/revision semantics.

🤖 Generated with Claude Code

mattdawkins and others added 2 commits July 22, 2026 20:29
Resizing a large suppression region on a frame with many detections
lagged and briefly hung on release. Every drag event bumps the
pending-save counter, which recomputed the dataset-wide fully-
suppressed set (every keyframe of every track, each 16x16
point-sampled against the region polygon) per mouse move, and the
per-frame suppression set was computed three times per update (canvas,
type counts, track list).

- getSuppressedTrackIds gains a cheap bbox-overlap upper bound so
  candidates that cannot possibly reach the coverage threshold skip
  the point sampling entirely.
- Results are memoized per store+frame for one edit revision (the
  pending-save counter), so the canvas, per-frame type counts, and
  track list share a single computation.
- The dataset-wide fully-suppressed totals recompute on a 500 ms
  debounce instead of synchronously on every save-counter bump, so
  corner drags stay responsive; the type-list totals settle right
  after the drag ends.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The debounced dataset-wide pass still ran at full price once a region
edit settled. Two further cuts:

- The fully-suppressed walk first collects the frames where any
  suppression region exists; a track with a keyframe on any other frame
  bails immediately, so frames without regions never reach the
  per-frame computation.
- Vertex-heavy region polygons (the suppressor's warped field-of-view
  shapes) are rasterized once per frame with a scanline fill, turning
  each coverage sample into an O(1) mask lookup instead of an
  O(vertices) point-in-polygon test. Simple polygons (<= 8 vertices)
  keep the exact test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mattdawkins
mattdawkins requested a review from BryonLewis July 23, 2026 13:02
BryonLewis and others added 4 commits July 23, 2026 17:36
Combine main's configurable threshold and attribute-suppression APIs with
this branch's revision cache, bbox prefilter, and region rasterization.

Co-authored-by: Cursor <cursoragent@cursor.com>
BryonLewis
BryonLewis previously approved these changes Jul 23, 2026

@BryonLewis BryonLewis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to fix a few minor issues:

  • pendingSavecount was declared multiple times in LayerManager.vue
  • Have FilterList use each regions tracks span so interpolated frames also count
  • a few other minor changes

@BryonLewis
BryonLewis merged commit 327978a into main Jul 23, 2026
3 checks passed
@BryonLewis
BryonLewis deleted the perf/suppression-computation branch July 23, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants