Skip to content

Speed up hot SurfTrackerData accessors (bit-identical)#1083

Open
robert-kofler42 wants to merge 1 commit into
ScrollPrize:mainfrom
robert-kofler42:perf/surftracker-hot-accessors
Open

Speed up hot SurfTrackerData accessors (bit-identical)#1083
robert-kofler42 wants to merge 1 commit into
ScrollPrize:mainfrom
robert-kofler42:perf/surftracker-hot-accessors

Conversation

@robert-kofler42

Copy link
Copy Markdown

What

valid_int, lookup_int, lookup_int_loc and surfsC in SurfTrackerData are called in the surface tracer's inner loop — the unwrapping hot path (the master plan's #1 bottleneck). Each did redundant work:

  • sm->rawPoints() called repeatedly — 6× in valid_int, 3× each in lookup_int / lookup_int_loc. rawPoints() is a virtual call that returns a cv::Mat header by value, i.e. an atomic refcount increment/decrement on the shared pixel data. So every use was a virtual dispatch + two atomic ops. Now bound once into a local const cv::Mat_<cv::Vec3f> and reused.
  • Double hash lookupslookup_int/valid_int did _data.contains(id) then loc(sm,p) (which is _data[{sm,p}]), two lookups of a non-trivial pair key; surfsC did contains() + find(). Each is now a single find().

Correctness — bit-identical

Same values, same control flow (contains() had already proved the key present, so the old operator[] never inserted). Verified by an output checksum over a synthetic SurfTrackerData/QuadSurface sweep — identical before/after — and the existing test_surf_tracker_data and merge tests pass.

Performance

Microbench (valid_int + lookup_int over a 150×150 entry grid, 40 sweeps, median of 7, -O3):

ns/cell
before 163
after 66

~2.5× faster on the accessor pair. These run per traced point, so the win lands directly on the segmentation/unwrapping inner loop. Bit-identical, no numeric change. Applies cleanly on main.

🤖 Generated with Claude Code

valid_int / lookup_int / lookup_int_loc / surfsC are called in the surface
tracer's inner loop (the unwrapping hot path). Each did redundant work:

- valid_int called sm->rawPoints() six times, lookup_int / lookup_int_loc
  three times each. rawPoints() is a virtual call that returns a cv::Mat
  header by value (atomic refcount increment/decrement on the shared pixel
  data) — so each call was a virtual dispatch plus two atomic ops. Bind it
  once into a local const cv::Mat_<cv::Vec3f> and reuse.
- lookup_int / valid_int did _data.contains(id) followed by loc(sm,p) (which
  is _data[{sm,p}]) — two hash lookups of a non-trivial pair key. surfsC did
  _surfs.contains(loc) + _surfs.find(loc). Replace each with a single find().

No numeric change: same values, same control flow (contains() already proved
the key present, so operator[] never inserted). Verified bit-identical by an
output checksum over a synthetic SurfTrackerData/QuadSurface sweep (identical
before/after) and the existing test_surf_tracker_data / merge tests pass.

Microbench (valid_int + lookup_int over a 150x150 grid, 40 sweeps, median):
163 ns/cell -> 66 ns/cell, ~2.5x faster on the accessor pair.
@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the scroll Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant