Skip to content

perf: Implement Adaptive Backpressure for VDOM Updates via Pre-Update Hooks #8996

@tobiu

Description

@tobiu

Context
In high-frequency update scenarios (e.g., Grid scrolling), ScrollManager currently 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

  1. Backpressure Check: The producer checks component.isVdomUpdating.
  2. Opt-Out: If true, the producer skips the heavy calculation (e.g., createViewData) and registers a Pre-Update Hook.
  3. Re-Entry: When the component finishes its current update (resolveVdomUpdate), it executes the registered Pre-Update Hook before checking needsVdomUpdate for the next cycle.

Proposed Changes

  1. src/manager/VDomUpdate.mjs:

    • Add preUpdateCallbackMap (Map<String, Function[]>).
    • Implement registerPreUpdate(ownerId, callback).
    • Implement executePreUpdates(ownerId): Executes callbacks and clears the list.
  2. src/mixin/VdomLifecycle.mjs:

    • Update 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();
      }
  3. 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

  • Zero Latency: No fixed timers. Updates happen as fast as the hardware allows.
  • Stability: Impossible to flood the queue, as new work is only scheduled when the previous work completes.
  • Efficiency: Skips redundant calculations during blocked periods.

Metadata

Metadata

Assignees

Labels

aicoreCore framework functionalityenhancementNew feature or requestperformancePerformance improvements and optimizations

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions