Tokio Tick Architecture
The backend engine uses smart timing to check for updates and send them to the display. This document explains how that timing works and why it’s efficient.How the Backend Checks for Updates
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ BACKEND UPDATE CHECKING │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ The engine constantly watches for two things: │
│ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ 1. NEW DATA 2. TIMER TICK │ │
│ │ from terminal (every 50ms at 60Hz) │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ └──────────────┬─────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ WHICH HAPPENED? │ │ │
│ │ └────────┬────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────┼─────────────┐ │ │
│ │ ▼ ▼ ▼ │ │
│ │ [New data] [Timer tick] [Both] │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ Process it Check timeouts Handle both │ │
│ │ Try to send │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
│ This runs continuously, handling whatever happens first │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
The Timer System
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ HOW THE TIMER WORKS │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ The engine uses a "timer wheel" - imagine a clock with many hands: │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Level 1: Milliseconds (64 slots) │ │
│ │ ══════════════════════════════════ │ │
│ │ [1ms][2ms][3ms]...[64ms] │ │
│ │ Handles: 0-64 millisecond delays │ │
│ │ │ │
│ │ Level 2: Seconds (64 slots) │ │
│ │ ═══════════════════════════════ │ │
│ │ [64ms][128ms]...[4 seconds] │ │
│ │ Handles: 64ms to 4 second delays │ │
│ │ │ │
│ │ Level 3-6: Minutes to Days │ │
│ │ ════════════════════════════════ │ │
│ │ For longer timeouts (confirmation, etc.) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ Why this matters: │
│ ────────────────── │
│ • Setting a timer: instant (O(1)) │
│ • Checking a timer: instant (O(1)) │
│ • Canceling a timer: instant (O(1)) │
│ │
│ No matter how many timers, operations stay fast! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
What Happens Each Tick
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ TICK OPERATIONS │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Every tick (50ms at 60Hz, 100ms at 30Hz): │
│ │
│ Step 1: Check Timeouts Cost: ~10 microseconds │
│ ═══════════════════════ │
│ • Is the multi-part operation taking too long? │
│ • Is the erase pattern detection expired? │
│ • Has the cursor been hidden too long? │
│ • Did the display forget to confirm? │
│ │
│ ───────────────────────────────────────────────────────────────────────── │
│ │
│ Step 2: Try to Send Update Cost: varies │
│ ══════════════════════════ │
│ │
│ ┌─────────────────────┬───────────────────────────────────────────────────┐ │
│ │ Situation │ What happens │ Cost │ │
│ ├─────────────────────┼───────────────────────────────────────┼──────────┤ │
│ │ No new data │ Do nothing │ ~5 μs │ │
│ │ Data, can't send │ Keep waiting │ ~5 μs │ │
│ │ Data, ready to send │ Build update and send │ ~1-10 ms │ │
│ └─────────────────────┴───────────────────────────────────────┴──────────┘ │
│ │
│ Most ticks are cheap (~15 μs) because usually nothing needs to happen! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Four Timeout Mechanisms
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ TIMEOUT SAFETY NETS │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ The engine has four timeout mechanisms to prevent getting stuck: │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 1. MULTI-PART OPERATION TIMEOUT │ │
│ │ ════════════════════════════════ │ │
│ │ When: Program sends "start" signal but never sends "end" │ │
│ │ Action: After timeout, proceed anyway │ │
│ │ Prevents: Infinite waiting for broken programs │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 2. ERASE PATTERN TIMEOUT │ │
│ │ ════════════════════════════ │ │
│ │ When: Screen erase detected, waiting for redraw │ │
│ │ Action: After timeout, show current state │ │
│ │ Prevents: Blank screen if redraw never comes │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 3. CURSOR HIDE TIMEOUT │ │
│ │ ══════════════════════════ │ │
│ │ When: Program hides cursor (fast typing mode) │ │
│ │ Action: After timeout, show cursor again │ │
│ │ Prevents: Permanently invisible cursor │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 4. CONFIRMATION TIMEOUT │ │
│ │ ═══════════════════════════ │ │
│ │ When: Display doesn't confirm receiving update │ │
│ │ Action: After 1 second, send next update anyway │ │
│ │ Prevents: Complete display freeze │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ All timeouts adjust automatically based on display speed! │
│ (60Hz = shorter timeouts, 30Hz = longer timeouts) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Tick Frequency Adapts to Display Speed
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ TICK RATE BY DISPLAY SPEED │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Display Speed Time Per Frame Tick Interval Ticks Per Second │
│ ═════════════ ══════════════ ═════════════ ════════════════ │
│ │
│ 120 Hz 8.3 ms 25 ms 40 ticks/sec │
│ (ProMotion) ████████████████████████████████████████ │
│ │
│ 60 Hz 16.7 ms 50 ms 20 ticks/sec │
│ (Standard) ████████████████████ │
│ │
│ 30 Hz 33.3 ms 100 ms 10 ticks/sec │
│ (Under load) ██████████ │
│ │
│ 20 Hz 50 ms 150 ms 6.7 ticks/sec │
│ (Heavy load) ███████ │
│ │
│ KEY BENEFIT: │
│ ════════════ │
│ 60Hz → 30Hz = 50% fewer ticks = 50% less work for backend │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Frame Duration Calculation
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ "WAIT FOR N FRAMES" - HOW IT WORKS │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Instead of fixed milliseconds, timeouts use "frames": │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ "Wait for 3 frames" │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────────────────────────────────────────┐ │ │
│ │ │ Get current display speed (e.g., 60 Hz) │ │ │
│ │ └───────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────────────────────────────────────────┐ │ │
│ │ │ Calculate: 1 second ÷ 60 = 16.7 ms per frame │ │ │
│ │ └───────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────────────────────────────────────────┐ │ │
│ │ │ Result: 3 × 16.7 ms = 50 ms │ │ │
│ │ └───────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ Examples: │
│ ══════════ │
│ @ 60 Hz: 3 frames = 50 ms │
│ @ 30 Hz: 3 frames = 100 ms │
│ @ 120 Hz: 3 frames = 25 ms │
│ │
│ Same "3 frames" adapts automatically to actual display speed! │
│ │
│ Calculation speed: ~4-8 nanoseconds (nearly instant) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Cost Savings When Display Slows Down
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 60 Hz VS 30 Hz COST COMPARISON │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 60 Hz 30 Hz Savings │
│ ════════════════════════════════════════════════════════════════════════ │
│ │
│ Ticks per second 20 10 50% │
│ ████████████████████ ██████████ │
│ │
│ Tick overhead ~400 μs/sec ~200 μs/sec 50% │
│ ████████████████████ ██████████ │
│ │
│ Timer operations 20/sec 10/sec 50% │
│ ████████████████████ ██████████ │
│ │
│ Timeout checks 20/sec 10/sec 50% │
│ ████████████████████ ██████████ │
│ │
│ ────────────────────────────────────────────────────────────────────────── │
│ │
│ TOTAL BACKEND ~1 ms/sec ~0.5 ms/sec 50% │
│ CPU USAGE ████████████████████ ██████████ │
│ │
│ When your computer gets busy, Monolex automatically does less work! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Summary
Timer Wheel
Instant timer operations no matter how many timers are running.
Dual Watching
Watches for both new data and timer ticks, handles whichever comes first.
Frame-Based Timing
Timeouts measured in frames, automatically adapt to display speed.
50% Less Work
When display slows down, backend does half the work automatically.
Related
- Display Timing - How display speed is measured
- Dual-Loop Architecture - Data Loop vs Render Loop
- Tauri IPC - Communication between backend and display
- Buffer Injection - How display updates work