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_INFINITY for non-numeric types (strings, booleans), causing infinite loops until maxIterations is 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 FormulaParser instance is created for every single cell during evaluation, causing massive memory churn and initialization overhead.

  • Solution:

    • Implement a singleton FormulaParser in the worker.

    • Use a mutable TaskContext to swap out the scopeMap and sheetId for 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) in useCalculationWorker.

  • 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) and Y.Doc (for sync).

    • Flow:

      1. React sends lightweight "Delta" (A1 = 5) to Worker.

      2. Worker updates internal WASM state.

      3. Worker recalculates affected dependencies in-memory (Zero-Copy).

      4. 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-wasm to include an EvaluationEngine.

    • 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.Doc on the Main Thread for networking and conflict resolution.

    • Create a "Bridge" that observes Y.Doc changes 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| ViewCache

Last updated

Was this helpful?