Skip to main content

WebKit requestAnimationFrame and Hz Detection

WebKit’s requestAnimationFrame (rAF) is the heartbeat of browser rendering. This document covers how Monolex detects actual display performance and adapts its timing system accordingly.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────────┐
│                    WEBKIT RAF IN MONOLEX ARCHITECTURE                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  Hardware Display (120Hz/60Hz/30Hz)                                             │
│       │                                                                         │
│       ▼                                                                         │
│  WebKit RAF Scheduler                                                           │
│       │ (measures actual frame timing)                                          │
│       ▼                                                                         │
│  DisplayTimingManager (TypeScript)                                              │
│       │ invoke("set_measured_fps", fps)                                         │
│       ▼                                                                         │
│  DisplayTiming (Rust)                                                           │
│       │ effective_hz.store(fps)                                                 │
│       ▼                                                                         │
│  GridWorker tick_interval                                                       │
│       │ frames(3) = 3 * (1000/fps) ms                                           │
│       ▼                                                                         │
│  Adapted timing throughout system                                               │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

RAF Callback Timing

WebKit calls RAF callbacks at the display’s refresh rate, but actual timing varies:
ConditionTypical RateBehavior
Normal operation60fpsCallbacks every 16.67ms
Background tab1fpsSeverely throttled
System load30-45fpsVariable interval
Low power mode30fpsPower-saving throttle

Hz Detection Flow

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              Hz DETECTION FLOW                                  │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   Frontend (RAF)                          Backend (Rust)                        │
│        │                                       │                                │
│        │ measureFrame()                        │                                │
│        │ track callback timing                 │                                │
│        │                                       │                                │
│        │ average over 60 samples               │                                │
│        │                                       │                                │
│        │ invoke("set_measured_fps")            │                                │
│        │──────────────────────────────────────►│                                │
│        │                                       │ set_measured(fps)              │
│        │                                       │ effective_hz.store()           │
│        │                                       │                                │
│        │                                       │ GridWorker reads               │
│        │                                       │ frames(n) uses new Hz          │
│        │                                       │                                │
└─────────────────────────────────────────────────────────────────────────────────┘

FPS Safety Limits

┌─────────────────────────────────────────────────────────────────┐
│  FPS VALUE SAFETY PROCESSING                                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Measured FPS arrives (e.g., 25, 60, 90)                       │
│        │                                                        │
│        ▼                                                        │
│   ┌─────────────────────────────────────────┐                   │
│   │  Apply Safety Limits                    │                   │
│   │                                         │                   │
│   │  Below 20? → Set to 20 (minimum)       │                   │
│   │  Above 120? → Cap at display max        │                   │
│   │  In range? → Use as-is                  │                   │
│   │                                         │                   │
│   └─────────────────────────────────────────┘                   │
│        │                                                        │
│        ▼                                                        │
│   Safe FPS value used for all timing                            │
│                                                                 │
│   Why limits?                                                   │
│   ───────────                                                   │
│   • 20fps minimum: Prevents system freeze                       │
│   • Display max: Never faster than screen can show              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Frame Duration Calculation

┌─────────────────────────────────────────────────────────────────┐
│  "WAIT FOR N FRAMES" CALCULATION                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Input: "Wait for 3 frames"                                    │
│                                                                 │
│   Calculation:                                                  │
│   ─────────────                                                 │
│   Frame duration = 1 second ÷ FPS                               │
│   Wait time = Frame duration × N                                │
│                                                                 │
│   Examples:                                                     │
│   ──────────                                                    │
│   @ 60fps: 1 frame = 16.7ms → 3 frames = 50ms                  │
│   @ 30fps: 1 frame = 33.3ms → 3 frames = 100ms                 │
│   @120fps: 1 frame = 8.3ms  → 3 frames = 25ms                  │
│                                                                 │
│   Speed: Nearly instant (billionths of a second)                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

System Load Impact

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         RAF RATE VS SYSTEM LOAD                                 │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   CPU Load      Measured FPS      Frame Budget      Notes                       │
│   ════════      ════════════      ════════════      ═════                       │
│                                                                                 │
│   10-30%        60 fps            16.67ms           Normal operation            │
│   50-70%        45-55 fps         18-22ms           Slight pressure             │
│   80-90%        30-40 fps         25-33ms           Heavy load                  │
│   95%+          20-30 fps         33-50ms           Severe throttling           │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Adaptive Response

When system load increases:
  1. WebKit naturally throttles RAF rate
  2. DisplayTimingManager detects lower fps
  3. Backend adjusts all frame-based timeouts
  4. Fewer IPC calls, larger batches
  5. System maintains stability under load

ProMotion Display Support

┌─────────────────────────────────────────────────────────────────┐
│  PROMOTION DISPLAY HANDLING                                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   MacBook Pro with ProMotion can run at:                        │
│                                                                 │
│   ┌──────────────────────────────────────────────────────────┐  │
│   │                                                          │  │
│   │   120Hz ████████████████████████  Smooth animation       │  │
│   │                                                          │  │
│   │   60Hz  ████████████             Normal operation        │  │
│   │                                                          │  │
│   │   24Hz  ████                     Static content          │  │
│   │                                                          │  │
│   └──────────────────────────────────────────────────────────┘  │
│                                                                 │
│   Monolex Detection:                                            │
│   ───────────────────                                           │
│   1. Check display capabilities on startup                      │
│   2. Set maximum allowed rate                                   │
│   3. Fallback to 60Hz if detection fails                        │
│                                                                 │
│   Benefit: Automatically uses your display's best rate          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Summary

RAF as Heartbeat

WebKit RAF timing reflects actual display performance.

60-Sample Average

Smooth FPS measurement over 60 frames (~1 second).

20-120Hz Range

Minimum 20fps floor, maximum hardware Hz cap.

~4-8ns Cost

Lock-free atomic operations for minimal overhead.