LearnNewsExamplesServices
Frontmatter
id9403
titlePerformance: Eliminate Path scrollTop Layout Thrashing in getTargetData
stateClosed
labels
enhancementaiperformance
assigneestobiu
createdAtMar 8, 2026, 11:44 PM
updatedAtMar 8, 2026, 11:59 PM
githubUrlhttps://github.com/neomjs/neo/issues/9403
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMar 8, 2026, 11:59 PM

Performance: Eliminate Path scrollTop Layout Thrashing in getTargetData

Closed v12.1.0 enhancementaiperformance
tobiu
tobiu commented on Mar 8, 2026, 11:44 PM

Problem: Profiling the Main Thread during rapid Grid scrolling reveals a secondary massive layout thrashing penalty:

  • Recalculate style: 50.6% total time
  • get scrollTop: 13.1% total time

This occurs because getTargetData unconditionally reads node.scrollTop and node.scrollLeft for every node in the event bubble path. When a grid row scrolls, the style tree is invalidated by VDOM delta mutations (set innerHTML, style.transform). Reading scrollTop on 15 ancestor elements immediately after these mutations forces the browser to synchronously recalculate layout 15 times per frame.

Proposed Solution: Pass an isTarget boolean into getTargetData(). For high-frequency continuous events like scroll and wheel, we only need the layout state of the actual node that generated the event (isTarget === true).

For all other elements in the event path (isTarget === false), we will skip reading scrollTop and scrollLeft and return undefined. By returning undefined rather than 0, we prevent the VDOM engine from misinterpreting the omission as a command to reset scroll positions to zero.

Additionally, we will convert the previous dimension skips (clientHeight, etc.) to return undefined rather than 0 for structural safety.

tobiu added the enhancement label on Mar 8, 2026, 11:44 PM
tobiu added the ai label on Mar 8, 2026, 11:44 PM
tobiu added the performance label on Mar 8, 2026, 11:44 PM
tobiu referenced in commit b10acf8 - "perf: Eliminate Path scrollTop Layout Thrashing in getTargetData (#9403)" on Mar 8, 2026, 11:57 PM
tobiu assigned to @tobiu on Mar 8, 2026, 11:58 PM
tobiu
tobiu Mar 8, 2026, 11:58 PM

Input from Gemini 3.1 Pro:

Task Completed:

  • Updated getTargetData to accept an isTarget boolean flag.
  • For high-frequency layout-thrashing events (scroll and wheel), the framework now skips reading scrollTop and scrollLeft for all nodes in the event's bubble path (isTarget === false).
  • Instead of returning 0 (which implies a valid coordinate that could reset scroll state in the VDOM engine), skipped geometric properties now return undefined to cleanly drop them from the serialized JSON payload.
  • The event.target continues to return its actual scrollTop, preserving critical scroll behavior for the components generating the event.

This targeted excision addresses the secondary layout thrashing bottleneck identified in the benchmarking, eliminating forced synchronous layouts on ancestor wrappers during grid scroll cycles.

tobiu closed this issue on Mar 8, 2026, 11:59 PM