Tauri IPC Architecture
When Monolex needs to show terminal content on screen, the backend engine must send data to the display. This document explains how that communication works and why it’s efficient.How Backend Talks to Display
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ BACKEND TO DISPLAY COMMUNICATION │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Backend Engine Display │
│ ══════════════ ═══════ │
│ │
│ Terminal data ready │
│ │ │
│ ▼ │
│ Convert to compact format │
│ │ │
│ └──────────────────────────────────▶ Receive data │
│ │ │
│ ▼ │
│ Wait for screen refresh │
│ │ │
│ ▼ │
│ Update display │
│ │ │
│ ◀──────────────────────────────────────────┘ │
│ Receive confirmation │
│ (ready for next update) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Communication Cost Breakdown
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ WHAT MAKES COMMUNICATION SLOW? │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Every message has two types of cost: │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ FIXED COST (per message) │ │
│ │ ───────────────────────── │ │
│ │ • Setting up the channel: ~50 microseconds │ │
│ │ • This happens EVERY time we send, regardless of size │ │
│ │ │ │
│ │ Think of it like: The cost of making a phone call │ │
│ │ (dialing, connecting) - same whether you talk 1 second or 1 hour │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ VARIABLE COST (per byte) │ │
│ │ ────────────────────────── │ │
│ │ • Transferring actual data: ~0.2 nanoseconds per byte │ │
│ │ • Very small compared to fixed cost │ │
│ │ │ │
│ │ Think of it like: The per-minute charge on a phone call │ │
│ │ (tiny compared to connection fee) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ KEY INSIGHT: │
│ ════════════ │
│ For a typical 8KB update: │
│ • Fixed cost: 50 microseconds (96% of total!) │
│ • Variable cost: 1.6 microseconds (only 4%) │
│ │
│ → Sending FEWER messages is more important than sending SMALLER messages │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
When to Send Updates
Before sending each update, the system asks 5 questions:Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ SHOULD WE SEND AN UPDATE? │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ New data arrives │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Q1: Still waiting for confirmation │ │
│ │ from last update? │────YES───▶ [WAIT - don't send] │
│ └───────────────────────────────────────┘ │
│ │ NO │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Q2: In the middle of a multi-part │ │
│ │ operation? (like clearing screen) │────YES───▶ [WAIT - collect more] │
│ └───────────────────────────────────────┘ │
│ │ NO │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Q3: Cursor temporarily hidden? │ │
│ │ (program is typing fast) │────YES───▶ [WAIT - let it finish] │
│ └───────────────────────────────────────┘ │
│ │ NO │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Q4: Detecting an erase pattern? │ │
│ │ (screen being redrawn) │────YES───▶ [WAIT - avoid flicker] │
│ └───────────────────────────────────────┘ │
│ │ NO │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Q5: Is there actually new data │ │
│ │ to show? │────NO────▶ [NOTHING TO SEND] │
│ └───────────────────────────────────────┘ │
│ │ YES │
│ ▼ │
│ ╔═══════════════════════════════════════╗ │
│ ║ ✓ SEND THE UPDATE! ║ │
│ ╚═══════════════════════════════════════╝ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Confirmation Handshake
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ CONFIRMATION PREVENTS OVERLOAD │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Time ───────────────────────────────────────────────────────────────▶ │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ 0ms │ │ 16ms │ │ 32ms │ │ 48ms │ │ 64ms │ │
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ │
│ [SEND]───[waiting]──[waiting]───[OK!]───[SEND]───[waiting]───[OK!] │
│ │ ▲ │ ▲ │
│ │ │ │ │ │
│ └────────────────────┘ └────────────────────┘ │
│ Confirmation Confirmation │
│ received received │
│ │
│ Without confirmation: │
│ ───────────────────── │
│ [SEND][SEND][SEND][SEND][SEND]───▶ Display overwhelmed! ❌ │
│ │
│ With confirmation: │
│ ────────────────── │
│ [SEND]────[OK!]────[SEND]────[OK!]───▶ Display keeps up! ✓ │
│ │
│ Result: ~30-40 smooth updates per second │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Compact vs Text Format
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ DATA FORMAT COMPARISON │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ TEXT FORMAT (like JSON) │
│ ═══════════════════════ │
│ {"cell":{"char":"A","fg":"#ff0000","bg":"#000000"}} │
│ │
│ • Human-readable but wasteful │
│ • Full screen = 194 KB │
│ • Slow to create: ~550 microseconds │
│ • Slow to read: ~600 microseconds │
│ │
│ ───────────────────────────────────────────────────────────────────────── │
│ │
│ COMPACT FORMAT (binary) │
│ ═══════════════════════ │
│ ┌────────────────────┐ │
│ │ Header (64 bytes) │ │
│ ├────────────────────┤ │
│ │ Line info │ │
│ ├────────────────────┤ │
│ │ Cell data │ ◀── Tightly packed, no wasted space │
│ ├────────────────────┤ │
│ │ Special chars │ │
│ └────────────────────┘ │
│ │
│ • Computer-optimized │
│ • Full screen = 57 KB (3.4x smaller!) │
│ • Fast to create: ~6 microseconds (90x faster!) │
│ • Fast to read: ~50 microseconds (12x faster!) │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Speed Comparison: 60Hz vs 30Hz
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ FEWER MESSAGES = LESS OVERHEAD │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 60 Hz (Normal Speed) │
│ ════════════════════ │
│ Messages per second: 60 │
│ Data per message: 8 KB │
│ Connection overhead: 60 × 50μs = 3 ms │
│ Transfer overhead: 480 KB × 0.2ns = 0.1 ms │
│ ──────────────────────────────────── │
│ TOTAL: 3.1 ms per second │
│ │
│ ───────────────────────────────────────────────────────────────────────── │
│ │
│ 30 Hz (Under Load) │
│ ══════════════════ │
│ Messages per second: 30 │
│ Data per message: 16 KB (doubled, accumulated) │
│ Connection overhead: 30 × 50μs = 1.5 ms │
│ Transfer overhead: 480 KB × 0.2ns = 0.1 ms │
│ ──────────────────────────────────── │
│ TOTAL: 1.6 ms per second │
│ │
│ ═══════════════════════════════════════════════════════════════════════════ │
│ │
│ SAVINGS: 1.5 ms/sec (48% reduction!) │
│ │
│ Same data transferred, half the overhead! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Complete Update Timing
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ HOW LONG DOES AN UPDATE TAKE? │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ FULL SCREEN UPDATE PARTIAL UPDATE (most common) │
│ ═══════════════════ ════════════════════════════ │
│ │
│ Receive data 0.05 ms Receive data 0.05 ms │
│ Process data 0.50 ms Process data 0.10 ms │
│ Prepare buffer 0.05 ms Prepare buffer 0.01 ms │
│ Wait for refresh 0.01 ms Wait for refresh 0.01 ms │
│ Parse update 0.01 ms Parse update 0.01 ms │
│ Update buffer 2.50 ms Update buffer 0.30 ms ◀── 8x faster! │
│ Update scroll 0.02 ms Update scroll 0.02 ms │
│ Render to screen 3.00 ms Render to screen 1.50 ms │
│ Send confirmation 0.05 ms Send confirmation 0.05 ms │
│ ───────────────────────── ───────────────────────── │
│ TOTAL: ~6.2 ms TOTAL: ~2.0 ms │
│ │
│ Partial updates are 3x faster because most of the screen stays the same! │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Automatic Adaptation Under Load
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ SYSTEM ADAPTS TO COMPUTER LOAD │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ COMPUTER NOT BUSY COMPUTER BUSY │
│ ════════════════════ ═══════════════ │
│ │
│ Connection cost: ~50 μs Connection cost: ~150 μs (3x slower) │
│ Updates per second: 60 Updates per second: 30 (auto-reduced) │
│ Total overhead: ~3 ms/sec Total overhead: ~4.5 ms/sec │
│ │
│ ───────────────────────────────────────────────────────────────────────── │
│ │
│ HOW IT WORKS: │
│ │
│ Computer gets busy │
│ │ │
│ ▼ │
│ Screen refresh rate drops (60fps → 30fps) │
│ │ │
│ ▼ │
│ Monolex detects the change │
│ │ │
│ ▼ │
│ Automatically sends fewer updates │
│ │ │
│ ▼ │
│ Each update contains more data (accumulated) │
│ │ │
│ ▼ │
│ 50% fewer connections, same visual result │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Why This Design Works
Copy
┌─────────────────────────────────────────────────────────────────────────────────┐
│ FOUR OPTIMIZATIONS WORKING TOGETHER │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. COMPACT DATA FORMAT │
│ ────────────────────── │
│ 3.4x smaller than text format │
│ Faster to create and read │
│ │
│ 2. SMART TIMING │
│ ─────────────── │
│ Adapts to screen refresh rate │
│ 50% fewer messages when system is busy │
│ │
│ 3. PARTIAL UPDATES │
│ ───────────────── │
│ Only sends what changed │
│ Skips unnecessary work │
│ │
│ 4. AUTOMATIC BATCHING │
│ ───────────────────── │
│ While waiting for confirmation, data accumulates │
│ Next message contains all accumulated changes │
│ No explicit batching code needed │
│ │
│ ═══════════════════════════════════════════════════════════════════════════ │
│ │
│ RESULT: Self-adapting system that stays smooth under any load │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Summary
Connection Cost Matters Most
96% of communication cost is connection overhead. Fewer messages = less overhead.
Confirmation Prevents Overload
Display confirms each update before receiving the next. Natural flow control.
48% Less Overhead
When system is busy, updates automatically batch together for efficiency.
Self-Adapting
No manual tuning needed. System optimizes itself based on actual performance.
Related
- Display Timing - How timing adapts to performance
- Dual-Loop Architecture - Data Loop vs Render Loop
- Tokio Tick - Backend timer architecture
- Buffer Injection - How display updates work