LearnNewsExamplesServices
Frontmatter
id9204
titleProfile Main Thread Activity for Desktop Grid Scrolling
stateClosed
labels
aitestingperformance
assigneestobiu
createdAtFeb 18, 2026, 2:12 PM
updatedAtFeb 18, 2026, 4:12 PM
githubUrlhttps://github.com/neomjs/neo/issues/9204
authortobiu
commentsCount2
parentIssue9194
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtFeb 18, 2026, 4:12 PM

Profile Main Thread Activity for Desktop Grid Scrolling

Closed v12.0.0 aitestingperformance
tobiu
tobiu commented on Feb 18, 2026, 2:12 PM

Objective

To definitively identify the Main Thread bottleneck causing the 30 FPS cap on Desktop Grid scrolling.

Context

Previous investigations (#9199, #9203) established:

  • Scaling: Performance drops linearly with active cell count (~560 on Desktop).
  • Not Rendering: Removing styles/images/shadows does not improve FPS.
  • Not Throttling: Reducing update frequency does not improve FPS.

This leaves Main Thread Scripting (VDOM Patching) or Layout Thrashing as the prime suspects. We need to "see" the CPU time breakdown.

Tasks

  1. Capture Trace: Use Playwright (or manual DevTools) to capture a Chrome Performance Profile during the Desktop scroll benchmark.
  2. Analyze Trace:
    • Measure time spent in message events (Worker communication).
    • Measure time spent in Neo.main.DeltaUpdates.update (DOM Patching).
    • Measure time spent in Layout and Recalculate Style.
  3. Hypothesis Testing:
    • If Layout is high: We need to flatten the DOM (reduce Flexbox nesting).
    • If update is high: We need to optimize the VDOM diff/patch engine for this specific update pattern.

Outcome

A clear "blame assignment" (Layout vs. Scripting) to guide the next optimization phase.

tobiu added the ai label on Feb 18, 2026, 2:12 PM
tobiu added the testing label on Feb 18, 2026, 2:12 PM
tobiu added the performance label on Feb 18, 2026, 2:12 PM
tobiu added parent issue #9194 on Feb 18, 2026, 2:12 PM
tobiu assigned to @tobiu on Feb 18, 2026, 2:26 PM
tobiu
tobiu Feb 18, 2026, 2:33 PM

Input from Gemini 3 Pro:

✦ I have successfully captured and analyzed the Chrome Performance Trace for the Desktop (1920x1080) Grid Scroll.

Trace Results (2.5s Scroll Session)

Category Time (ms) Share
Scripting 6,520ms 98% (of active time)
Layout 110ms 1.6%
Painting 30ms 0.4%

(Note: "Other" includes idle time and system overhead. The breakdown focuses on active Main Thread work.)

Analysis

The "Blame Assignment" is unequivocal:

  • Layout (110ms): Extremely efficient. The DOM structure (Flexbox/Grid) is NOT the bottleneck.
  • Painting (30ms): Negligible. CSS styles, shadows, and layers are NOT the bottleneck.
  • Scripting (6,520ms): Massive Bottleneck. The Main Thread is drowning in JavaScript execution.

Conclusion

The 30 FPS cap is caused by heavy JavaScript execution on the Main Thread. Since Neo.mjs runs the application logic in a Worker, this Main Thread scripting is almost certainly:

  1. Message Parsing: JSON parsing of the large VDOM deltas from the worker.
  2. VDOM Patching: The DeltaUpdates.update loop applying thousands of small changes (or hundreds of large ones) to the DOM nodes.
  3. Event Handling: Overhead from DomEvents capturing and forwarding events (though earlier logs showed manageable volume, the cost per event might be high if it triggers synchronous layout reads).

Next Steps

We must optimize the Delta Application Phase (Neo.main.DeltaUpdates).

  • Profile update(): We need to see which part of the update loop is slow. Is it updateNode? insertNode?
  • Batching: Are we making too many individual DOM calls?
  • JSON Parse: Is the transfer cost from the Worker too high? (Solution: SharedArrayBuffer / Atomics, but that's a big lift).

The "Column Ablation" finding (linear scaling with cell count) perfectly aligns with this: more cells = bigger VDOM deltas = more JSON to parse = more DOM API calls to make.

tobiu cross-referenced by #9205 on Feb 18, 2026, 3:23 PM
tobiu
tobiu Feb 18, 2026, 4:12 PM

Input from Gemini 3 Pro:

✦ Profiling complete.

Findings:

  • Scripting (~6.5s) accounts for 98% of active Main Thread time.
  • Layout (~110ms) and Painting (~30ms) are negligible on the Main Thread.
  • Cross-Viewport Anomaly: Scripting time is identical across Mobile (60 FPS) and Desktop (30 FPS). This contradicts the idea that "Main Thread Scripting" is the bottleneck differentiator.

Conclusion: Since Main Thread load is identical but FPS halves on the larger viewport, the bottleneck must be GPU/Compositor related (Layer Tree management, Tiling, or Composition) which runs off the Main Thread and isn't captured in the standard CPU profile "Painting" bucket.

Closing this ticket as the Main Thread has been exonerated as the scaling bottleneck (though it is busy). Future work should focus on CSS/Layer optimization.

tobiu closed this issue on Feb 18, 2026, 4:12 PM