LearnNewsExamplesServices
Frontmatter
id9401
titlePerformance: Proxy Getter Hoisting in Grid Row & Array Slice Optimization
stateClosed
labels
enhancementaiperformance
assigneestobiu
createdAtMar 8, 2026, 10:40 PM
updatedAtMar 8, 2026, 10:59 PM
githubUrlhttps://github.com/neomjs/neo/issues/9401
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMar 8, 2026, 10:59 PM

Performance: Proxy Getter Hoisting in Grid Row & Array Slice Optimization

Closed v12.1.0 enhancementaiperformance
tobiu
tobiu commented on Mar 8, 2026, 10:40 PM

Problem: Profiling the App Worker during fast grid scrolling reveals that the reactive Config getters (Neo.mjs:348 and Base.mjs:971) consume a massive 17.4% of total self-time.

A significant portion of this overhead comes from src/grid/Row.mjs. During createVdom, the Row iterates over every column cell and calls applyRendererOutput. Inside applyRendererOutput, it queries me.parent, me.parent.parent, gridBody.store, gridBody.selectedCells, and gridBody.colspanField.

Because these are reactive array/object configs, querying them inside a 1,500-iteration hot loop triggers thousands of proxy intercepts and forces the framework to shallow-clone arrays (selectedCells) thousands of times per frame.

Furthermore, the default array cloning mechanism in Neo.mjs uses [...value], which is inherently slower than the native value.slice().

Proposed Solution:

  1. Getter Hoisting: Inside Row.mjs:createVdom, destructure all needed gridBody and gridContainer properties exactly once. Pass these stable references down into applyRendererOutput to completely bypass the getter proxy in the hot loop.
  2. V8 Optimization: In Neo.mjs config getter trap, replace the legacy array clone logic value = [...value] with value = value.slice() for faster native array copies.
tobiu added the enhancement label on Mar 8, 2026, 10:40 PM
tobiu added the ai label on Mar 8, 2026, 10:40 PM
tobiu added the performance label on Mar 8, 2026, 10:40 PM
tobiu referenced in commit 7fb9286 - "perf: Proxy Getter Hoisting in Grid Row & Array Slice Optimization (#9401)" on Mar 8, 2026, 10:58 PM
tobiu assigned to @tobiu on Mar 8, 2026, 10:59 PM
tobiu
tobiu Mar 8, 2026, 10:59 PM

Input from Gemini 3.1 Pro:

Task Completed:

  • Array Slice Optimization: Replaced the legacy [...value] spread operator with the native V8 fast-path value.slice() inside the Neo.mjs reactive config getter interceptor. This speeds up all framework array clones (e.g. items, columns, selectedRows).
  • Proxy Getter Hoisting: Refactored src/grid/Row.mjs:createVdom() to destructure all needed gridBody and gridContainer reactive configs once before the column loops.
  • Param Passing: Updated applyRendererOutput() to accept a cache object containing these hoisted values, completely bypassing thousands of proxy intercepts and shallow array clones that were previously triggered on every single cell render during grid scrolling.
tobiu closed this issue on Mar 8, 2026, 10:59 PM