Skip to content

perf(list): reduce row render churn - #618

Closed
JustYannicc wants to merge 121 commits into
SuperCmdLabs:mainfrom
JustYannicc:codex/perf-list-grid-row-render-churn
Closed

perf(list): reduce row render churn#618
JustYannicc wants to merge 121 commits into
SuperCmdLabs:mainfrom
JustYannicc:codex/perf-list-grid-row-render-churn

Conversation

@JustYannicc

Copy link
Copy Markdown
Collaborator

What changed

  • Memoized ListItemRenderer and ListEmojiGridItemRenderer with focused comparators that track visible/data props and ignore handler identity churn.
  • Added scripts/measure-raycast-list-render-churn.mjs to instrument list and emoji-row render churn.
  • Added scripts/test-list-renderer-memoization.mjs covering comparator behavior and select/activate/context-menu callback wiring.

Why

Selection, action overlay, scroll, and other parent state changes can recreate visible row handlers even when row visuals do not change. Before this change, that made every visible list row or emoji cell re-enter render. The grid path already had this memoization pattern, so list rows now match that lower-churn behavior.

Compatibility impact

No Raycast API behavior or extension-facing props were removed or changed. Selection styling, data indexes, assets path icon rendering, accessories, activation, hover selection, and context-menu behavior remain wired through the same props.

How tested

  • node --test scripts/test-list-renderer-memoization.mjs
  • node --test scripts/test-list-renderer-memoization.mjs scripts/test-list-registry-stable-order.mjs
  • node scripts/run-node-tests.mjs --exclude-perf (317 passed, 1 skipped)
  • ./node_modules/.bin/tsc -p tsconfig.renderer.json --noEmit --pretty false
  • ./node_modules/.bin/vite build
  • LSP diagnostics on src/renderer/src/raycast-api/list-runtime-renderers.tsx: no diagnostics found

Performance evidence

Benchmark command: node scripts/measure-raycast-list-render-churn.mjs --visible-rows=80 --visible-emoji-cells=96 --selection-steps=300 --parent-updates=150 --iterations=5 --warmups=1

Before:

  • list selection churn: 24000 renders, median 293.661ms
  • list parent churn: 12000 renders, median 138.918ms
  • emoji selection churn: 28800 renders, median 126.492ms
  • emoji parent churn: 14400 renders, median 63.981ms

After:

  • list selection churn: 600 renders, median 43.205ms
  • list parent churn: 0 renders, median 15.695ms
  • emoji selection churn: 600 renders, median 34.449ms
  • emoji parent churn: 0 renders, median 15.965ms

Stack validation

Started from codex/perf-wave4-integrated-stack-20260705 at exact SHA ac90ce403aeddab98d0a1b245afce268c48b8bfd. Opened this branch as JustYannicc:codex/perf-list-grid-row-render-churn targeting SuperCmdLabs/SuperCmd:main.

Validated the grid audit finding: GridItemRenderer already uses React.memo with a comparator that ignores handler identity. No grid-path changes were made because the list memoization produced the targeted churn reduction without touching virtualization behavior.

Note: npm run typecheck:renderer is blocked on this machine because the npm wrapper routes to pnpm and the repo parity check requires a real npm binary with package-lock.json; the equivalent underlying renderer tsc command passed directly.

Replaces

None.

(cherry picked from commit 83c2a89)
(cherry picked from commit 0a7560b)
# Conflicts:
#	src/renderer/src/raycast-api/hooks/use-cached-promise.ts
…launcher surfaces

# Conflicts:
#	src/renderer/src/raycast-api/list-runtime-renderers.tsx
#	src/renderer/src/raycast-api/list-runtime.tsx
…IO stalls

# Conflicts:
#	src/renderer/src/CameraExtension.tsx
# Conflicts:
#	src/renderer/src/raycast-api/list-runtime.tsx
…resh overhead

# Conflicts:
#	scripts/bench-script-command-discovery.mjs
#	scripts/benchmark-file-search-delete-batch.mjs
#	scripts/lib/script-command-runner-harness.mjs
#	scripts/lib/ts-import.mjs
#	scripts/test-file-search-delete-batch.mjs
#	scripts/test-script-command-runner.mjs
#	src/main/file-search-index.ts
#	src/main/main.ts
…hurn

# Conflicts:
#	scripts/lib/script-command-runner-harness.mjs
#	scripts/lib/ts-import.mjs
#	scripts/test-extension-lifecycle-sandbox.mjs
#	scripts/test-script-command-runner.mjs
#	src/main/main.ts
#	src/renderer/src/ExtensionView.tsx
… hot paths

# Conflicts:
#	scripts/test-use-frecency-sorting.mjs
#	src/renderer/src/raycast-api/form-runtime.tsx
#	src/renderer/src/raycast-api/grid-runtime-hooks.ts
#	src/renderer/src/raycast-api/grid-runtime-items.tsx
#	src/renderer/src/raycast-api/hooks/use-frecency-sorting.ts
# Conflicts:
#	.github/workflows/project-checks.yml
#	package.json
#	scripts/file-search-perf-harness.mjs
#	scripts/test-browser-search-performance.mjs
#	scripts/test-file-search-perf-harness.mjs
#	scripts/test-root-search-perf.mjs
#	src/renderer/src/CameraExtension.tsx
#	src/renderer/src/hooks/useBrowserSearch.ts
#	src/renderer/src/raycast-api/list-runtime.tsx
…cle and media fixes

# Conflicts:
#	scripts/lib/ts-import.mjs
#	scripts/measure-extension-bundle-cache.mjs
#	src/main/commands.ts
#	src/main/extension-runner.ts
#	src/main/main.ts
#	src/renderer/src/ExtensionView.tsx
#	src/renderer/src/raycast-api/grid-runtime-hooks.ts
#	src/renderer/src/raycast-api/list-runtime-hooks.ts
@JustYannicc

Copy link
Copy Markdown
Collaborator Author

Superseded by consolidated renderer/Raycast wave5 PR #621: #621

@JustYannicc JustYannicc closed this Jul 5, 2026
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