Frontmatter
| id | 8996 |
| title | perf: Implement Adaptive Backpressure for VDOM Updates via Pre-Update Hooks |
| state | Closed |
| labels | enhancementaiperformancecore |
| assignees | tobiu |
| createdAt | Feb 5, 2026, 1:44 AM |
| updatedAt | Feb 5, 2026, 2:19 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8996 |
| author | tobiu |
| commentsCount | 2 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Feb 5, 2026, 2:16 AM |
perf: Implement Adaptive Backpressure for VDOM Updates via Pre-Update Hooks

Input from Gemini 3 Pro:
✦ I have implemented the Adaptive Backpressure system to eliminate the fixed throttle dependency and prevent message queue flooding.
Changes Implemented:
Neo.manager.VDomUpdate: AddedpreUpdateMap,registerPreUpdate(id, callback), andexecutePreUpdates(id). This allows components to queue logic that must run immediately after their current update finishes but before the next update cycle starts.Neo.mixin.VdomLifecycle: UpdatedresolveVdomUpdateto callVDomUpdate.executePreUpdates(me.id). This ensures queued logic (likecreateViewData) runs at the earliest possible safe moment, potentially settingneedsVdomUpdateto trigger the next frame instantly.Neo.grid.Body: RefactoredcreateViewDatato checkme.isVdomUpdating. If true, it aborts the calculation and registers itself viaregisterPreUpdateto retry automatically when the engine is free.Neo.grid.ScrollManager: Reverted the conservative48msthrottle back to16ms(approx 60fps). The grid now self-regulates: it runs at full speed on fast hardware and throttles gracefully on slow hardware without accumulating a backlog.This architecture ensures zero input lag and maximum frame rate for the given hardware capability.

Input from Gemini 3 Pro:
✦ Architectural Note: We implemented the backpressure check directly inside
GridBody.createViewDatarather than in the consumer (ScrollManager).Rationale:
createViewDatais the single point of entry for the expensive row calculation logic. By placing the guard and registration logic here, we protect the component from all potential triggers (Scroll events, Resize events, Store data changes, manual calls), not just scrolling. This encapsulation ensures the grid self-regulates its CPU usage under any heavy load scenario, providing a more robust and universal performance guarantee.
Context In high-frequency update scenarios (e.g., Grid scrolling),
ScrollManagercurrently uses a fixed throttle (e.g., 48ms) to prevent flooding the VDOM worker with updates the Main Thread cannot consume fast enough ("Death Spiral").While effective, a fixed timer is not adaptive. It caps performance on high-end devices (which could handle >20fps) and might still be too aggressive for very low-end devices.
The Goal Implement Adaptive Backpressure where the producer (ScrollManager) automatically scales its update rate based on the consumer's (Main Thread) capacity.
The Mechanism
component.isVdomUpdating.true, the producer skips the heavy calculation (e.g.,createViewData) and registers a Pre-Update Hook.resolveVdomUpdate), it executes the registered Pre-Update Hook before checkingneedsVdomUpdatefor the next cycle.Proposed Changes
src/manager/VDomUpdate.mjs:preUpdateCallbackMap(Map<String, Function[]>).registerPreUpdate(ownerId, callback).executePreUpdates(ownerId): Executes callbacks and clears the list.src/mixin/VdomLifecycle.mjs:resolveVdomUpdate:// ... existing logic ... VDomUpdate.unregisterInFlightUpdate(me.id); VDomUpdate.triggerPostUpdates(me.id); // NEW: Execute Pre-Update Hooks (e.g. re-run createViewData) VDomUpdate.executePreUpdates(me.id); if (me.needsVdomUpdate) { me.update(); }Usage (Example):
// ScrollManager.mjs if (gridBody.isVdomUpdating) { // Queue the work for immediately after the current frame clears Neo.manager.VDomUpdate.registerPreUpdate(gridBody.id, () => { // This sets needsVdomUpdate = true internally gridBody.createViewData(); }); return; }Benefits