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:| Condition | Typical Rate | Behavior |
|---|---|---|
| Normal operation | 60fps | Callbacks every 16.67ms |
| Background tab | 1fps | Severely throttled |
| System load | 30-45fps | Variable interval |
| Low power mode | 30fps | Power-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:- WebKit naturally throttles RAF rate
- DisplayTimingManager detects lower fps
- Backend adjusts all frame-based timeouts
- Fewer IPC calls, larger batches
- 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.
Related
- Overview - Adaptive timing system overview
- Tokio Tick - How Rust timer uses Hz
- Control Layers - Hz (Outer) vs ACK (Inner)