Skip to main content

Control Layers: Hz (Outer) vs ACK (Inner)

The Monolex render pipeline has two control mechanisms that operate at different layers:
  • Hz Detection = Outer Control Layer (Rust side)
  • ACK Gating = Inner Control Layer (TypeScript side)

The Layered Architecture

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│                              CONTROL LAYER ARCHITECTURE                                 │
│                                                                                         │
│  ┌───────────────────────────────────────────────────────────────────────────────────┐ │
│  │                                                                                   │ │
│  │   ╔═══════════════════════════════════════════════════════════════════════════╗  │ │
│  │   ║                                                                           ║  │ │
│  │   ║   OUTER CONTROL LAYER (Hz Detection)                                      ║  │ │
│  │   ║   ═══════════════════════════════════════════════════════════════════════ ║  │ │
│  │   ║                                                                           ║  │ │
│  │   ║   Scope: Entire Rust backend                                              ║  │ │
│  │   ║   Controls: tick_interval (how often we attempt to render)                ║  │ │
│  │   ║   Measured from: WebKit requestAnimationFrame                             ║  │ │
│  │   ║   Applied to: Rust tokio timer                                            ║  │ │
│  │   ║                                                                           ║  │ │
│  │   ║   ┌─────────────────────────────────────────────────────────────────────┐ ║  │ │
│  │   ║   │                                                                     │ ║  │ │
│  │   ║   │   tick()  ───►  tick()  ───►  tick()  ───►  tick()                 │ ║  │ │
│  │   ║   │     │             │             │             │                     │ ║  │ │
│  │   ║   │     ▼             ▼             ▼             ▼                     │ ║  │ │
│  │   ║   │   pull()        pull()        pull()        pull()                  │ ║  │ │
│  │   ║   │     │             │             │             │                     │ ║  │ │
│  │   ║   │     ▼             ▼             ▼             ▼                     │ ║  │ │
│  │   ║   │   hash          hash          hash          hash                    │ ║  │ │
│  │   ║   │     │             │             │             │                     │ ║  │ │
│  │   ║   │     ▼             ▼             ▼             ▼                     │ ║  │ │
│  │   ║   │                                                                     │ ║  │ │
│  │   ║   │   60Hz: ████████████████████████████████████████  (20 ops/sec)     │ ║  │ │
│  │   ║   │   30Hz: ████████████████████                      (10 ops/sec)     │ ║  │ │
│  │   ║   │                                                                     │ ║  │ │
│  │   ║   └─────────────────────────────────────────────────────────────────────┘ ║  │ │
│  │   ║                                                                           ║  │ │
│  │   ║                              │                                            ║  │ │
│  │   ║                              │ emit()                                     ║  │ │
│  │   ║                              ▼                                            ║  │ │
│  │   ║                                                                           ║  │ │
│  │   ║   ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ║  │ │
│  │   ║                                                                         ║  │ │
│  │   ║   │   INNER CONTROL LAYER (ACK Gating)                                 │ ║  │ │
│  │   ║       ═══════════════════════════════════════════════════════════════   ║  │ │
│  │   ║   │                                                                     │ ║  │ │
│  │   ║       Scope: TypeScript frontend                                        ║  │ │
│  │   ║   │   Controls: waiting_ack (whether we can emit this frame)           │ ║  │ │
│  │   ║       Mechanism: Backpressure from frontend                             ║  │ │
│  │   ║   │                                                                     │ ║  │ │
│  │   ║       ┌─────────────────────────────────────────────────────────────┐   ║  │ │
│  │   ║   │   │                                                             │   ║  │ │
│  │   ║       │   onGridUpdate()  ───►  decode()  ───►  inject()           │   ║  │ │
│  │   ║   │   │        │                                    │               │   ║  │ │
│  │   ║       │        ▼                                    ▼               │   ║  │ │
│  │   ║   │   │   BufferLine[]                        WebGL Render          │   ║  │ │
│  │   ║       │                                             │               │   ║  │ │
│  │   ║   │   │                                             ▼               │   ║  │ │
│  │   ║       │                                      requestAnimationFrame  │   ║  │ │
│  │   ║   │   │                                             │               │   ║  │ │
│  │   ║       │                                             ▼               │   ║  │ │
│  │   ║   │   │   ack()  ◄──────────────────────────  Render Complete       │   ║  │ │
│  │   ║       │     │                                                       │   ║  │ │
│  │   ║   │   │     │                                                       │   ║  │ │
│  │   ║       └─────┼───────────────────────────────────────────────────────┘   ║  │ │
│  │   ║   │         │                                                       │   ║  │ │
│  │   ║             │ waiting_ack = false                                       ║  │ │
│  │   ║   │         │                                                       │   ║  │ │
│  │   ║   └ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ ║  │ │
│  │   ║             │                                                           ║  │ │
│  │   ║             ▼                                                           ║  │ │
│  │   ║   (next emit allowed)                                                   ║  │ │
│  │   ║                                                                           ║  │ │
│  │   ╚═══════════════════════════════════════════════════════════════════════════╝  │ │
│  │                                                                                   │ │
│  └───────────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Why “Outer” and “Inner”?

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   CONCENTRIC CONTROL LAYERS                                                             │
│                                                                                         │
│   ┌─────────────────────────────────────────────────────────────────────────────────┐  │
│   │                                                                                 │  │
│   │    ┌─────────────────────────────────────────────────────────────────────────┐ │  │
│   │    │                                                                         │ │  │
│   │    │   ┌─────────────────────────────────────────────────────────────────┐  │ │  │
│   │    │   │                                                                 │  │ │  │
│   │    │   │   ┌─────────────────────────────────────────────────────────┐  │  │ │  │
│   │    │   │   │                                                         │  │  │ │  │
│   │    │   │   │                      👁️ USER                            │  │  │ │  │
│   │    │   │   │                                                         │  │  │ │  │
│   │    │   │   └─────────────────────────────────────────────────────────┘  │  │ │  │
│   │    │   │                                                                 │  │ │  │
│   │    │   │                    INNER: ACK (TS Layer)                        │  │ │  │
│   │    │   │                    - decode, inject, WebGL                      │  │ │  │
│   │    │   │                    - Protects frontend from overload            │  │ │  │
│   │    │   │                                                                 │  │ │  │
│   │    │   └─────────────────────────────────────────────────────────────────┘  │ │  │
│   │    │                                                                         │ │  │
│   │    │                    OUTER: Hz (Rust Layer)                               │ │  │
│   │    │                    - tick, pull, hash, emit                             │ │  │
│   │    │                    - Controls how often we attempt to render            │ │  │
│   │    │                                                                         │ │  │
│   │    └─────────────────────────────────────────────────────────────────────────┘ │  │
│   │                                                                                 │  │
│   │                    DATA INGESTION (No control - always runs)                   │  │
│   │                    - PTY, VTE, Grid                                            │  │
│   │                                                                                 │  │
│   └─────────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘
LayerControlWhy This Name
Outer (Hz)RustWraps around the entire IPC boundary. Controls the rate of all render attempts.
Inner (ACK)TypeScriptInside the render path. Controls whether a specific emit is allowed.

Side-by-Side Comparison

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   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"                  │
│                                         │                                               │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Pipeline Flow with Control Layers

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   DATA FLOW WITH CONTROL LAYERS                                                         │
│                                                                                         │
│                                                                                         │
│   PTY ──► feed() ──► VTE ──► Grid                                                       │
│                               │                                                         │
│                               │ pending_data = true                                     │
│                               ▼                                                         │
│   ╔═══════════════════════════════════════════════════════════════════════════════════╗ │
│   ║                                                                                   ║ │
│   ║   OUTER LAYER (Hz Control)                                                        ║ │
│   ║   ────────────────────────────────────────────────────────────────────────────    ║ │
│   ║                                                                                   ║ │
│   ║   tick_interval.tick()  ◄──── Hz Detection sets interval                         ║ │
│   ║         │                                                                         ║ │
│   ║         ▼                                                                         ║ │
│   ║   ┌─────────────┐                                                                 ║ │
│   ║   │   tick()    │  timeout checks                                                 ║ │
│   ║   └──────┬──────┘                                                                 ║ │
│   ║          │                                                                        ║ │
│   ║          ▼                                                                        ║ │
│   ║   ┌─────────────┐                                                                 ║ │
│   ║   │   pull()    │  read grid, compute hash, build update                          ║ │
│   ║   │             │                                                                 ║ │
│   ║   │  ┌──────────────────────────────────────────────────────────────────────┐    ║ │
│   ║   │  │                                                                      │    ║ │
│   ║   │  │   INNER LAYER (ACK Control)                                          │    ║ │
│   ║   │  │   ────────────────────────────────────────────────────────────────   │    ║ │
│   ║   │  │                                                                      │    ║ │
│   ║   │  │   waiting_ack?                                                       │    ║ │
│   ║   │  │       │                                                              │    ║ │
│   ║   │  │       ├── true  ──► return None (don't emit)                        │    ║ │
│   ║   │  │       │                                                              │    ║ │
│   ║   │  │       └── false ──► return Some(GridUpdate)                         │    ║ │
│   ║   │  │                            │                                         │    ║ │
│   ║   │  │                            ▼                                         │    ║ │
│   ║   │  │                     ┌─────────────┐                                  │    ║ │
│   ║   │  │                     │   emit()    │                                  │    ║ │
│   ║   │  │                     └──────┬──────┘                                  │    ║ │
│   ║   │  │                            │                                         │    ║ │
│   ║   │  │                            │ IPC                                     │    ║ │
│   ║   │  │                            ▼                                         │    ║ │
│   ║   │  │                     ┌─────────────┐                                  │    ║ │
│   ║   │  │                     │  Frontend   │                                  │    ║ │
│   ║   │  │                     │  decode()   │                                  │    ║ │
│   ║   │  │                     │  inject()   │                                  │    ║ │
│   ║   │  │                     │  WebGL      │                                  │    ║ │
│   ║   │  │                     └──────┬──────┘                                  │    ║ │
│   ║   │  │                            │                                         │    ║ │
│   ║   │  │                            │ ack()                                   │    ║ │
│   ║   │  │                            ▼                                         │    ║ │
│   ║   │  │                     waiting_ack = false                              │    ║ │
│   ║   │  │                                                                      │    ║ │
│   ║   │  └──────────────────────────────────────────────────────────────────────┘    ║ │
│   ║   │             │                                                                 ║ │
│   ║   └─────────────┘                                                                 ║ │
│   ║                                                                                   ║ │
│   ╚═══════════════════════════════════════════════════════════════════════════════════╝ │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Cost Reduction Summary

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   WHERE COSTS ARE REDUCED                                                               │
│                                                                                         │
│   RUST BACKEND (Outer Layer)           │   FRONTEND / TS (Inner Layer)                 │
│   ══════════════════════════════════   │   ══════════════════════════════════════════  │
│                                        │                                               │
│   tick()          ← Hz reduces this    │                                               │
│   tick()          ← Hz reduces this    │                                               │
│   pull()          ← Hz reduces this    │                                               │
│   hash compute    ← Hz reduces this    │                                               │
│   build_update()  ← Hz reduces this    │                                               │
│                                        │                                               │
│   ───────────────── emit() ────────────┼─────────────────────────────────────────────  │
│                      │                 │                                               │
│                      │                 │   onGridUpdate()    ← ACK reduces this        │
│                      │                 │   decode()          ← ACK reduces this        │
│                      │                 │   inject()          ← ACK reduces this        │
│                      │                 │   WebGL render      ← ACK reduces this        │
│                      │                 │                                               │
│                      │◄────────────────┼── ack()                                       │
│                                        │                                               │
└────────────────────────────────────────┴───────────────────────────────────────────────┘

Summary Table

AspectOuter (Hz)Inner (ACK)
LayerRust backendTypeScript frontend
Mechanismtick_interval durationwaiting_ack flag
ControlsRender attempt frequencyEmit permission
ReducesRust CPU, scheduler overheadTS CPU, WebGL calls
StrategyProactiveReactive
AnalogyFactory production rateShipping gate check

Key Insight

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                         │
│   Hz (Outer):  Controls HOW OFTEN we try                                                │
│                "Factory production rate"                                                │
│                                                                                         │
│   ACK (Inner): Controls WHETHER we can send                                             │
│                "Shipping gate check"                                                    │
│                                                                                         │
│   ───────────────────────────────────────────────────────────────────────────────────   │
│                                                                                         │
│   Hz reduces Rust workload     (outer layer savings)                                    │
│   ACK protects TS from overload (inner layer protection)                                │
│                                                                                         │
│   Together: Optimal efficiency across both layers                                       │
│                                                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Summary

Hz = Outer Control

Rust-side timer interval. Controls how often we attempt to render.

ACK = Inner Control

TypeScript-side backpressure. Controls whether we can emit this frame.

Proactive vs Reactive

Hz slows down before hitting wall. ACK stops when wall is hit.

Layered Protection

Two layers ensure optimal efficiency across entire pipeline.