Skip to content

perf: eliminate O(n) hot-path scans in graph data management and tracker - #28

Merged
veillette merged 1 commit into
mainfrom
claude/fix-performance-bottlenecks-H97A8
Feb 22, 2026
Merged

perf: eliminate O(n) hot-path scans in graph data management and tracker#28
veillette merged 1 commit into
mainfrom
claude/fix-performance-bottlenecks-H97A8

Conversation

@veillette

Copy link
Copy Markdown
Collaborator

GraphDataManager (issues 1 & 2):

  • Replace dataPoints: Vector2[] with a fixed-size ring buffer (O(1)
    eviction vs. O(n) Array.shift reindexing on every oldest-point removal)
  • Maintain running xMin/xMax/yMin/yMax updated incrementally in O(1);
    a full O(n) recomputeMinMax() rescan fires only when an evicted point
    was an axis extreme (rare once the buffer is settled)
  • applyAxisRangesFromExtremes() replaces the previous updateAxisRanges()
    full-scan, keeping axis rescaling at O(1) on the 30 Hz tracking path
  • addDataPoints() updates min/max inline per-point to avoid per-call
    function overhead in the tight loop

OpenCVTracker (issue 3):

  • Split captureFrame() into drawVideoFrame() (GPU rasterise — fast) and
    readPixels(x,y,w,h) (CPU readback — expensive)
  • track() now computes a search window around lastMatchCenter and calls
    getImageData only over that sub-region, reducing GPU→CPU pixel transfer
    by ~10–15× for typical template sizes at 30 Hz
  • Falls back to a full-frame search when no prior match exists or the
    clamped window cannot contain the template
  • lastMatchCenter seeded from initFromVideo() so the very first track()
    call benefits from the windowed path immediately

https://claude.ai/code/session_01E8HRtu2MvwhJYDGSu4ucPa

GraphDataManager (issues 1 & 2):
- Replace dataPoints: Vector2[] with a fixed-size ring buffer (O(1)
  eviction vs. O(n) Array.shift reindexing on every oldest-point removal)
- Maintain running xMin/xMax/yMin/yMax updated incrementally in O(1);
  a full O(n) recomputeMinMax() rescan fires only when an evicted point
  was an axis extreme (rare once the buffer is settled)
- applyAxisRangesFromExtremes() replaces the previous updateAxisRanges()
  full-scan, keeping axis rescaling at O(1) on the 30 Hz tracking path
- addDataPoints() updates min/max inline per-point to avoid per-call
  function overhead in the tight loop

OpenCVTracker (issue 3):
- Split captureFrame() into drawVideoFrame() (GPU rasterise — fast) and
  readPixels(x,y,w,h) (CPU readback — expensive)
- track() now computes a search window around lastMatchCenter and calls
  getImageData only over that sub-region, reducing GPU→CPU pixel transfer
  by ~10–15× for typical template sizes at 30 Hz
- Falls back to a full-frame search when no prior match exists or the
  clamped window cannot contain the template
- lastMatchCenter seeded from initFromVideo() so the very first track()
  call benefits from the windowed path immediately

https://claude.ai/code/session_01E8HRtu2MvwhJYDGSu4ucPa
@veillette
veillette merged commit d3369b9 into main Feb 22, 2026
1 check failed
@veillette
veillette deleted the claude/fix-performance-bottlenecks-H97A8 branch February 22, 2026 19:39
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