> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WebKit requestAnimationFrame

> How WebKit RAF drives Hz detection and adaptive timing

# 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:

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

<CardGroup cols={2}>
  <Card title="RAF as Heartbeat" icon="heart-pulse">
    WebKit RAF timing reflects actual display performance.
  </Card>

  <Card title="60-Sample Average" icon="calculator">
    Smooth FPS measurement over 60 frames (\~1 second).
  </Card>

  <Card title="20-120Hz Range" icon="gauge">
    Minimum 20fps floor, maximum hardware Hz cap.
  </Card>

  <Card title="~4-8ns Cost" icon="bolt">
    Lock-free atomic operations for minimal overhead.
  </Card>
</CardGroup>

## Related

* [Overview](/terminal/adaptive-timing/overview) - Adaptive timing system overview
* [Tokio Tick](/terminal/adaptive-timing/internals/tokio-tick) - How Rust timer uses Hz
* [Control Layers](/terminal/adaptive-timing/control-layers) - Hz (Outer) vs ACK (Inner)
