Skip to content

Perf: Index findViewById to avoid O(n) tree walk per lookup#2

Draft
collinversluis wants to merge 1 commit into
mainfrom
claude/perf-pr2-findviewbyid-index
Draft

Perf: Index findViewById to avoid O(n) tree walk per lookup#2
collinversluis wants to merge 1 commit into
mainfrom
claude/perf-pr2-findviewbyid-index

Conversation

@collinversluis

Copy link
Copy Markdown
Member

Summary

findViewById walks the entire element tree on every call. On element-heavy pages this is O(n²) when many lookups happen during boot (each element's parent lookup triggers a walk).

Add an id→view index, populated on view add and invalidated on view remove. Lookups become O(1).

  • 1 file, ~85 LoC
  • Drop-in replacement — existing call signature preserved
  • Invalidation hooks already wired in this diff

Impact

Profile attribution: this lookup accumulated ~60-100ms self-time on a 200-widget bench. Should scale further on pages with deeper trees.

Test plan

  • Add/remove elements via UI — verify index stays consistent
  • Drag-reorder elements — verify lookups still resolve correctly
  • Document switch (navigate to a different page) — verify index is rebuilt cleanly
  • Undo/redo cycles — verify no stale entries

Notes

Cherry-pick from claude/great-mayer-klkFh. No experiment flag — invalidation is unconditional. If the team prefers a flag for the first release, happy to gate it.


Generated by Claude Code

Phase 7 of the perf series.

CPU profile on a 200-element page showed findViewRecursive at 509ms self-time,
called ~420 times during boot via findViewById (316) and findContainerById (104).
Each call was an O(n) walk of the full Marionette view tree.

This builds a Map<id, view> index lazily on first findViewById call within a
frame, clears it via requestAnimationFrame, and validates _isDestroyed before
returning a cached view. Cache misses fall through to a rebuild-and-retry so
mid-frame view creation/destruction is handled safely.

For the boot scenario (~420 lookups across ~200 elements in a tight burst), this
turns 420 * 200 = 84,000 ops into ~200 (build) + 420 (lookups) ≈ 620 ops.

Gated by e_memoize_active_controls.
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