Architecture
Thread Ownership
Main Thread Owns
- Application state
- VNode tree construction
- Layout computation
- Focus management
- Drawlist builder
- Event parsing and routing
Worker Thread Owns
- Native engine instance
- Terminal I/O (read/write)
- Frame scheduling
- Event polling loop
- Frame transport buffers (when using SAB)
Frame Transport
Frames (ZRDL drawlists) are transferred from main to worker via one of two mechanisms:Transfer Mode
Mechanism: Copy drawlistArrayBuffer via postMessage with [buffer] transfer list.
Flow:
- Works everywhere (no SharedArrayBuffer requirement)
- Zero-copy transfer of ownership
- Main thread cannot reuse buffer immediately
- Slight latency from
postMessage
SAB Mailbox Mode
Mechanism: Write drawlist to pre-allocated SharedArrayBuffer mailbox slot. Structure:state(u32) — 0=FREE, 1=WRITING, 2=READYpublishedSeq(u32) — Sequence number of published framepublishedToken(u32) — Token for validationpublishedBytes(u32) — Byte length of drawlistconsumedSeq(u32) — Sequence number of consumed frame
- Zero-copy submission
- Main thread can immediately reuse builder
- Lower latency than
postMessage
- Requires
SharedArrayBuffersupport - Slightly higher memory usage (pre-allocated slots)
packages/node/src/worker/protocol.ts
Backpressure Handling
Frame Skipping
When frames arrive faster than the worker can process them: Strategy: Skip intermediate frames, always present the latest frame.SAB Mailbox Saturation
When all mailbox slots are full: Strategy: Fall back to transfer mode for that frame.Event Batching
Events are batched into ZREV batches to reducepostMessage overhead:
postMessage cost across multiple events.
Worker Lifecycle
Initialization
Frame Loop
fpsCap:
packages/node/src/worker/tickTiming.ts
Shutdown
Message Protocol
Main → Worker
Worker → Main
packages/node/src/worker/protocol.ts
Performance Considerations
Worker Spawn Overhead
Spawning a worker thread has ~5-10ms overhead on Node.js 18. Mitigation: Useauto mode, which prefers inline for low FPS.
postMessage Latency
postMessage with transfer has ~0.1-0.5ms latency.
Mitigation: Use SAB mailbox mode for high-frequency updates.
Memory Overhead
Worker mode uses ~20-40 MB more memory than inline mode (worker runtime + buffers). Acceptable for: Interactive apps where responsiveness matters.Related Documentation
- Node.js Backend — Backend implementation
- Native Addon — N-API binding
- Benchmarks — Worker vs. inline performance