Roadmap
This document outlines the planned architectural improvements to evolve the spreadsheet engine into a high-performance, WebAssembly-driven calculation platform.
Phase 1: Critical Reliability & Performance Fixes
(Status: Planned)
1. Fix Iterative Calculation Convergence
Problem: Circular dependency checks currently return
POSITIVE_INFINITYfor non-numeric types (strings, booleans), causing infinite loops untilmaxIterationsis hit.Solution: Implement strict equality checks (
===) for non-numeric values in the convergence detection logic.Impact: Prevents wasted CPU cycles and unresponsive workers during circular reference evaluation involving status toggles or text.
2. Optimize Formula Parser Instantiation
Problem: A new
FormulaParserinstance is created for every single cell during evaluation, causing massive memory churn and initialization overhead.Solution:
Implement a singleton
FormulaParserin the worker.Use a mutable
TaskContextto swap out thescopeMapandsheetIdfor each evaluation pass without recreating the parser.
Impact: Significant reduction in garbage collection pauses and faster batch processing.
3. Coalesce User Inputs
Problem: Rapid user inputs (e.g., dragging a handle, fast typing) can flood the worker with calculation requests.
Solution: Set a default
coalesceDelayMs(e.g., 16ms) inuseCalculationWorker.Impact: Smoother UI interactions by batching rapid-fire updates into single calculation frames.
Phase 2: Architecture Evolution (WASM & Rust)
(Status: Design Phase)
1. In-Memory Cell Store (The "Source of Truth" Shift)
Move the authoritative state from React/JS to the Web Worker (Rust/WASM).
Current Architecture:
React holds state → Serializes JSON → Worker calculates → Returns JSON.
Performance bottleneck: Data serialization and Main Thread blocking.
New Architecture:
Worker/WASM: Acts as the In-Memory Database. Stores
Grid { cells: HashMap<Coord, CellData> }.React: Acts as the "View". Stores only the
ViewportCache(visible cells) andY.Doc(for sync).Flow:
React sends lightweight "Delta" (
A1 = 5) to Worker.Worker updates internal WASM state.
Worker recalculates affected dependencies in-memory (Zero-Copy).
Worker sends back only the diffs (
B1 changed to 10).
Impact: 60 FPS rendering regardless of dataset size (1M+ rows).
2. Rust-Based Formula Evaluation
Goal: Replace
fast-formula-parser(JS) with a Rust-based evaluation engine.Why: JS parsing is slow; Rust allows SIMD optimizations for array formulas and strictly typed math.
Plan:
Expand
dag-wasmto include anEvaluationEngine.Port standard Excel functions to Rust.
Expose
evaluate(formula: &str)directly to the DAG.
3. Yjs Synchronization Bridge
Goal: Efficiently sync concurrent edits (CRDTs) with the linear memory of WASM.
Implementation:
Use
Y.Docon the Main Thread for networking and conflict resolution.Create a "Bridge" that observes
Y.Docchanges and pushes binary/flat updates to the Worker.Worker treats these updates as "External Inputs" and never writes back to Yjs directly (Unidirectional Data Flow).
Phase 3: Excel Compatibility & Advanced Features
1. Precision & Date Systems
Date Systems: Add support for both 1900 and 1904 date systems (Excel compatibility).
Number Precision: Handle IEEE 754 floating-point quirks (e.g.,
0.1 + 0.2) to match Excel's 15-digit precision behavior.
2. "Smart" Range Recalculation
Problem: Dependencies on large ranges (e.g.,
SUM(A1:A10000)) trigger massive data transfers.Solution: With the In-Memory Cell Store, range functions read directly from WASM memory. No data transfer is required between the calculation logic and the data store.
Architecture Diagrams
Data Flow (Target State)
graph TD
User[User Input] --> React[React Main Thread]
subgraph "Main Thread (View & Sync)"
React -->|1. Optimistic Update| ViewCache[Viewport Cache (Zustand/useState)]
ViewCache -->|Render| UI[Grid Component]
React -->|2. Sync Changes| YDoc[Yjs Doc (CRDT)]
YDoc -->|3. Observe & Broadcast| Bridge[Sync Bridge]
end
Bridge -->|4. Push Delta (Binary/JSON)| Worker[Web Worker]
subgraph "Worker Thread (The Brain)"
Worker -->|5. Update Memory| WasmStore[WASM Cell Store]
subgraph "Rust/WASM Engine"
WasmStore -->|Read| DAG[Dependency Graph]
DAG -->|Topological Sort| Calc[Calculation Engine]
Calc -->|Evaluate (In-Memory)| WasmStore
end
WasmStore -->|6. Extract Diff| DiffGen[Diff Generator]
end
DiffGen -->|7. Computed Updates (Visible Only)| React
React -->|8. Merge Diffs| ViewCacheLast updated
Was this helpful?