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

# Display Timing System

> How Monolex adapts to system load through WebKit FPS measurement and frame-based timing

# Display Timing System

Monolex uses an adaptive timing system that measures actual WebKit rendering performance and adjusts the entire backend accordingly. This provides optimal efficiency under varying system loads.

## Overview

```
┌─────────────────────────────────────────────────────────────────┐
│  ADAPTIVE TIMING ARCHITECTURE                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Hardware Display (120Hz/60Hz/30Hz)                             │
│       │                                                         │
│       ▼                                                         │
│  WebKit measureWebKitFps()                                      │
│       │ Measures actual rAF callback rate                       │
│       │                                                         │
│       ▼                                                         │
│  invoke("set_measured_fps", 30)                                 │
│       │                                                         │
│       ▼                                                         │
│  Rust DisplayTiming                                             │
│       │ effective_hz.store(30)                                  │
│       │                                                         │
│       ▼                                                         │
│  All frame-based timing adapts:                                 │
│       • tick_interval = frames(3) = 100ms                       │
│       • sync_deadline = frames(1) = 33ms                        │
│       • resize_settle = frames(6) = 200ms                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

## Why Adaptive Timing?

WebKit's `requestAnimationFrame` rate varies based on system conditions:

| Condition      | Typical FPS | Cause                |
| -------------- | ----------- | -------------------- |
| Normal         | 60 fps      | Standard operation   |
| System load    | 30 fps      | CPU contention       |
| Background tab | 1 fps       | Browser throttling   |
| ProMotion      | 120 fps     | High refresh display |

Without adaptive timing, the backend would continue operating at 60Hz even when WebKit can only render at 30fps, wasting CPU cycles.

## Two Control Layers

Monolex uses two complementary mechanisms to optimize rendering:

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   OUTER CONTROL (Hz)                    │    INNER CONTROL (ACK)                        │
│   ══════════════════════════════════════│════════════════════════════════════════════   │
│                                         │                                               │
│   Location: Rust backend                │    Location: TypeScript frontend              │
│                                         │                                               │
│   Mechanism:                            │    Mechanism:                                 │
│     tick_interval = frames(3)           │      waiting_ack flag                         │
│     60Hz → 50ms                         │      true → block emit                        │
│     30Hz → 100ms                        │      false → allow emit                       │
│                                         │                                               │
│   What it controls:                     │    What it controls:                          │
│     • tick() frequency                  │      • emit() permission                      │
│     • pull() frequency                  │      • Prevents TS overload                   │
│     • hash computation frequency        │                                               │
│     • Overall render attempt rate       │                                               │
│                                         │                                               │
│   Cost saved:                           │    Cost saved:                                │
│     • Rust CPU cycles                   │      • TS CPU cycles                          │
│     • tokio scheduler overhead          │      • decode() calls                         │
│                                         │      • inject() calls                         │
│                                         │      • WebGL render calls                     │
│                                         │                                               │
│   When it helps:                        │    When it helps:                             │
│     System under load                   │      Frontend busy processing                 │
│     → WebKit RAF slows down             │      → ACK delayed                            │
│     → Hz detection measures 30fps       │      → waiting_ack stays true                 │
│     → tick_interval becomes 100ms       │      → emit blocked until ACK                 │
│     → Rust does less work               │      → Frontend not overwhelmed               │
│                                         │                                               │
│   Proactive:                            │    Reactive:                                  │
│     "Slow down before hitting wall"     │      "Stop when wall is hit"                  │
│                                         │                                               │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```

### Hz Detection (Outer Control)

Controls **how often** the backend attempts to render:

* Measures WebKit FPS using requestAnimationFrame
* Updates `effective_hz` atomically in Rust
* All frame-based durations scale automatically

```
┌─────────────────────────────────────────────────────────────────┐
│  FRAME-BASED TIMING CALCULATION                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   "Wait for 3 frames"                                           │
│        │                                                        │
│        ├── @ 60Hz: 3 × 16.7ms = 50ms                           │
│        │                                                        │
│        └── @ 30Hz: 3 × 33.3ms = 100ms                          │
│                                                                 │
│   Result: Same "3 frames" adapts to actual display speed        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### ACK Gating (Inner Control)

Controls **whether** each emit is allowed:

* Frontend sends ACK after processing each frame
* Backend blocks next emit until ACK received
* Prevents frontend overload

```
┌─────────────────────────────────────────────────────────────────┐
│  ACK GATING LOGIC                                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Is frontend still processing?                                 │
│        │                                                        │
│        ├── YES → Wait (don't send new frame)                   │
│        │                                                        │
│        └── NO → Send update, then wait for confirmation        │
│                                                                 │
│   This prevents overwhelming the display                        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

## Cost Savings

When Hz drops from 60 to 30:

| Component        | 60Hz | 30Hz  | Reduction |
| ---------------- | ---- | ----- | --------- |
| tick() calls/sec | 20   | 10    | 50%       |
| pull() calls/sec | 20   | 10    | 50%       |
| emit() calls/sec | \~10 | \~10  | Same      |
| Rust CPU usage   | 100% | \~50% | 50%       |

The key insight: both mechanisms produce the same emit rate (\~10/sec at 30fps), but Hz detection reduces **backend work** while ACK gating prevents **frontend overload**.

## Measurement Process

```
┌─────────────────────────────────────────────────────────────────┐
│  FPS MEASUREMENT PROCESS                                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Step 1: Count 60 screen refreshes                             │
│           │                                                     │
│           ▼                                                     │
│   Step 2: Measure how long it took                              │
│           │                                                     │
│           ▼                                                     │
│   Step 3: Calculate: 60 ÷ time = FPS                            │
│           │                                                     │
│           ▼                                                     │
│   Result: Actual display performance (30, 45, 60, 120 fps)      │
│                                                                 │
│   Example:                                                      │
│   ─────────                                                     │
│   60 frames in 1000ms → 60 fps (normal)                         │
│   60 frames in 2000ms → 30 fps (system under load)              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### Adaptive Intervals

* Normal (≥30 fps): Measure every 3 seconds
* Low (\< 30 fps): Measure every 1 second

## Self-Regulating System

The timing system creates a natural feedback loop:

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   SELF-REGULATING FEEDBACK LOOP                                                         │
│                                                                                         │
│   System Load ↑                                                                         │
│        │                                                                                │
│        ▼                                                                                │
│   WebKit FPS ↓ (60 → 30)                                                                │
│        │                                                                                │
│        ▼                                                                                │
│   DisplayTiming measures drop                                                           │
│        │                                                                                │
│        ▼                                                                                │
│   tick_interval increases (50ms → 100ms)                                                │
│        │                                                                                │
│        ▼                                                                                │
│   Rust does less work                                                                   │
│        │                                                                                │
│        ▼                                                                                │
│   System Load ↓                                                                         │
│        │                                                                                │
│        ▼                                                                                │
│   (cycle continues)                                                                     │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```

This self-regulation prevents the terminal from contributing to system overload.

## How It Works

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   DISPLAY TIMING SYSTEM                                                                 │
│                                                                                         │
│   ┌─────────────────────────────────────────────────────────────────────────────────┐  │
│   │                                                                                 │  │
│   │   FRONTEND (Measures Display)                                                   │  │
│   │   ────────────────────────────                                                  │  │
│   │                                                                                 │  │
│   │   ┌────────────┐    ┌────────────┐    ┌────────────┐                           │  │
│   │   │ Count 60   │───▶│ Calculate  │───▶│ Report to  │                           │  │
│   │   │ frames     │    │ FPS        │    │ Backend    │                           │  │
│   │   └────────────┘    └────────────┘    └─────┬──────┘                           │  │
│   │                                             │                                   │  │
│   │   Repeats every 1-3 seconds                 │                                   │  │
│   │                                             │                                   │  │
│   └─────────────────────────────────────────────┼───────────────────────────────────┘  │
│                                                 │                                      │
│                                                 ▼                                      │
│   ┌─────────────────────────────────────────────────────────────────────────────────┐  │
│   │                                                                                 │  │
│   │   BACKEND (Adapts Timing)                                                       │  │
│   │   ────────────────────────                                                      │  │
│   │                                                                                 │  │
│   │   ┌────────────┐    ┌────────────┐    ┌────────────┐                           │  │
│   │   │ Receive    │───▶│ Cap at     │───▶│ Update all │                           │  │
│   │   │ FPS value  │    │ 20-120 Hz  │    │ timers     │                           │  │
│   │   └────────────┘    └────────────┘    └────────────┘                           │  │
│   │                                                                                 │  │
│   │   Safety: Never below 20fps, never above display max                            │  │
│   │                                                                                 │  │
│   └─────────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```

## Why Both Are Needed

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│  Hz Detection alone:                                                                    │
│  ───────────────────                                                                    │
│  • Reduces tick frequency based on MEASURED display rate                                │
│  • But if measurement is wrong, could overwhelm frontend                                │
│  • Needs ACK as safety net                                                              │
│                                                                                         │
│  ACK alone:                                                                             │
│  ──────────                                                                             │
│  • Prevents frontend overload (backpressure)                                            │
│  • But Rust still does unnecessary work (wasted ticks)                                  │
│  • Needs Hz Detection to reduce base rate                                               │
│                                                                                         │
│  Together:                                                                              │
│  ─────────                                                                              │
│  • Hz Detection = "Don't try too often" (proactive)                                     │
│  • ACK = "Don't send if not ready" (reactive)                                           │
│  • Optimal efficiency with safety fallback                                              │
│                                                                                         │
│  ═══════════════════════════════════════════════════════════════════════════════════    │
│                                                                                         │
│  Hz Detection: "Know beforehand, run slower" (proactive rate adaptation)                │
│  ACK Only:     "Run fast, wait when blocked" (reactive backpressure)                    │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```

## Key Points

<CardGroup cols={2}>
  <Card title="Hz Detection" icon="gauge">
    Controls Rust backend tick rate. Proactive optimization that reduces work before overload.
  </Card>

  <Card title="ACK Gating" icon="shield">
    Protects frontend from overload. Reactive backpressure that blocks when busy.
  </Card>

  <Card title="Lock-Free" icon="bolt">
    Uses AtomicU32 for thread-safe, lock-free Hz sharing across async tasks.
  </Card>

  <Card title="Self-Regulating" icon="rotate">
    Creates natural feedback loop that prevents terminal from contributing to system load.
  </Card>
</CardGroup>

## Related

* [Pipeline Architecture](/terminal/adaptive-timing/pipeline) - 10-stage pipeline with control points
* [Dual-Loop Architecture](/terminal/adaptive-timing/dual-loop) - Data Loop vs Render Loop
* [Control Layers](/terminal/adaptive-timing/control-layers) - Hz (Outer) vs ACK (Inner)
* [WebKit RAF](/terminal/adaptive-timing/internals/webkit-raf) - FPS measurement internals
* [Tokio Tick](/terminal/adaptive-timing/internals/tokio-tick) - GridWorker tick architecture
* [Buffer Injection](/terminal/adaptive-timing/internals/buffer-injection) - Frontend buffer handling
* [Tauri IPC](/terminal/adaptive-timing/internals/tauri-ipc) - IPC costs and batching
* [Atomic State](/terminal/atomic-state) - State machine that uses frame-based timing
* [Data Flow](/terminal/data-flow) - How data moves through the pipeline
