Skip to main content

Systems-Grade Benchmarking

SoulState is engineered for high-density reactive environments. Unlike libraries optimized for simple benchmarks with 10 subscribers, SoulState is designed to maintain predictable performance as your application scales to 100,000+ active subscribers.

📊 Sparse Update Supremacy

Workload: 100,000 subscribers, 100 state keys, 1% update impact (surgical).

In this scenario, updating a single key only affects 1,000 out of 100,000 subscribers.

LibraryThroughput (hz)Scalability Identity
SoulState~250,900Surgical DAG Runtime
Jotai~193,800Atomic State
Zustand~280Global Broadcast
Redux Toolkit~170Centralized Reducer

Analysis: The O(M) Advantage

  • Zustand/RTK: These libraries use a global broadcast model ($O(N)$). When any state changes, they must iterate through all 100,000 subscribers and run selectors.
  • SoulState: Uses an Invalidation Graph ($O(M)$). It knows exactly which 1,000 subscribers care about the changed key and notifies them directly, skipping the other 99,000 entirely.

🏗️ Deep Propagation Performance

Workload: 10 levels of nested computed state, 1,000 subscribers.

SoulState's level-based propagation ensures that derived state is recomputed only once per update, in the correct topological order.

LibraryThroughput (hz)Consistency
SoulState~549,900Deterministic / Glitch-Free
Zustand~19,700Manual Optimization Required

⚖️ The Systems-Grade Tradeoff

SoulState is not a "silver bullet." Its architecture makes specific tradeoffs to achieve its scalability.

1. Initialization Overhead

Building the Invalidation Graph takes time. SoulState is significantly slower than Zustand at creating subscribers.

  • Zustand: Optimized for high-churn, short-lived components.
  • SoulState: Optimized for long-lived, high-density reactive graphs.

2. Memory Footprint

SoulState maintains a bidirectional graph and topological levels for every subscriber.

  • Overhead: ~150-200 bytes per subscriber node.
  • Total: 100,000 subscribers will consume ~20MB of heap for the dependency graph.

🔍 Benchmark Methodology

All benchmarks are executed using vitest bench with the following environment:

  • Environment: Node.js 20+ / V8 Engine.
  • Workload: Identical selector and listener logic across all competitors.
  • Warmup: 500ms warmup period to allow JIT optimization.
  • Repetition: Minimum 10 runs to ensure statistical stability.

Reproducibility

You can reproduce these results by running:

npm run test:bench

🛠️ Performance Best Practices

  1. Granular Selectors: Always select the smallest possible piece of state to minimize $M$ (affected nodes).
  2. Computed Chains: Use computed nodes for expensive transformations. SoulState's graph will ensure they are only re-run when their specific dependencies change.
  3. Avoid Selective "God Objects": If your selector returns a massive object that changes frequently, you lose the benefits of sparse invalidation.

Performance Summary

SoulState is the right choice when your application's update complexity outweighs its initialization complexity. If you have 10,000+ components that need to stay in sync with a central store, SoulState's graph architecture provides the only path to predictable 60fps performance.