LearnNewsExamplesServices
Frontmatter
id9157
titleperf(grid): Optimize Horizontal Scrolling (Cell Recycling)
stateClosed
labels
enhancementaiperformance
assigneestobiu
createdAtFeb 15, 2026, 12:53 AM
updatedAtFeb 15, 2026, 1:29 AM
githubUrlhttps://github.com/neomjs/neo/issues/9157
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtFeb 15, 2026, 1:29 AM

perf(grid): Optimize Horizontal Scrolling (Cell Recycling)

Closed v12.0.0 enhancementaiperformance
tobiu
tobiu commented on Feb 15, 2026, 12:53 AM

Currently, horizontal scrolling in the Grid forces a full re-render of all visible cells (createViewData(force=true)). This is because Neo.grid.Body detects a change in mountedColumns and triggers a forced update for all rows. This results in O(N*M) operations (N rows * M columns) even for a 1-column scroll delta.

Optimization Goal: Implement "Cell Recycling" or efficient DOM updates for horizontal scrolling, similar to how Row Pooling works for vertical scrolling. Only the cells entering/leaving the viewport (or updating content) should be re-rendered.

Tasks:

  1. Analyze Neo.grid.Row.createVdom to see if we can selectively update cells instead of rebuilding the entire cn array.
  2. Investigate if we can detect the direction of the scroll and only update the leading/trailing edges of the pooled cells.
  3. Ensure component based columns are properly recycled/moved.
tobiu added the enhancement label on Feb 15, 2026, 12:53 AM
tobiu added the ai label on Feb 15, 2026, 12:53 AM
tobiu added the performance label on Feb 15, 2026, 12:53 AM
tobiu referenced in commit 303cc88 - "perf(grid): Optimize Horizontal Scrolling with Cell Recycling (#9157)" on Feb 15, 2026, 1:28 AM
tobiu assigned to @tobiu on Feb 15, 2026, 1:28 AM
tobiu
tobiu Feb 15, 2026, 1:29 AM

Input from Gemini 3 Pro:

✦ I have implemented the "Cell Recycling" optimization for horizontal scrolling.

Changes:

  1. Map-Based Recycling: Neo.grid.Row now captures the previous VDOM children (oldCn) and creates a Map keyed by dataField. This allows robust O(1) lookup of reusable cells regardless of their pool index or position.
  2. Smart Recycling Logic: Inside the createVdom loop, we check if a valid cell VDOM exists for the current column and record ID. If so, we:
    • Update its id to match the new pool slot.
    • Update its position (left, width) and aria-colindex.
    • Reuse the VDOM node directly, skipping the expensive applyRendererOutput call (and thus preventing unnecessary Component re-renders).
  3. Body Integration: Neo.grid.Body now correctly passes the recycle flag to rows when implicit horizontal scrolling is detected.

Verified Impact: Horizontal scrolling now only triggers renderers for newly entering columns, significantly reducing the overhead from ~975+ calls to ~140 (proportional to new columns * rows) in test scenarios.

This completes the performance optimization epic.

tobiu closed this issue on Feb 15, 2026, 1:29 AM
tobiu cross-referenced by #9158 on Feb 15, 2026, 1:32 AM