Skip to content

devagrawal09/js-reactivity-benchmark

Repository files navigation

JS Reactivity Benchmark

This benchmark is designed to measure the performance of JavaScript frontend frameworks and reactive libraries in handling complex, dynamic data updates and queries, complementing the focus of the existing JS Framework Benchmark.

What is this benchmark?

The JS Reactivity Benchmark simulates a data-driven application with multiple, interdependent UI components, all displaying different reactive views (queries) over the same large, in-memory dataset. Its primary goal is to evaluate how efficiently frameworks handle:

  1. Reactive Query Execution: The performance of defining and automatically re-running queries (filtering, sorting, joining, aggregating, projecting, paginating) as the underlying data changes.
  2. Fine-Grained UI Updates: How effectively the framework translates the results of these reactive queries into minimal and timely updates in the DOM, especially when many different views need to update from a single data change.
  3. Event Propagation: The overhead and efficiency of routing simulated user/system events to the reactive system to trigger state changes and subsequent UI updates.

How it Differs from the JS Framework Benchmark

The standard JS Framework Benchmark primarily measures:

  • Raw rendering speed: How quickly frameworks can create and update large numbers of DOM elements from a simple, structured dataset (a list).
  • Virtual DOM/Templating efficiency: The performance of the framework's mechanism for mapping a straightforward data structure to a visual representation, focusing on batch list operations (create, update 10th, delete, swap).
  • Direct data-to-UI mapping: The benchmark tests scenarios where there's a relatively direct, one-to-one or one-to-many mapping from a single data list to the UI representation.

The JS Reactivity Benchmark, on the other hand, measures:

  • The full reactive pipeline: From an event -> data change -> query re-computation -> UI update.
  • Complex data dependencies: How frameworks handle UI derived from multiple tables, joins, aggregations, and filtered/sorted subsets of data.
  • Overlapping views: How efficiently the system manages many different reactive queries over the same data, where a single data change may require multiple views to update simultaneously.
  • Decision logic performance: The overhead of the reactive system's internal work to determine what needs to re-run (queries) and what in the UI needs to update based on granular state changes.

In essence, while the JS Framework Benchmark tests the efficiency of rendering given a data structure, the JS Reactivity Benchmark tests the efficiency of the entire process of reactively deriving and updating the UI in response to dynamic events and data relationships.

Who Should Care About This Benchmark?

This benchmark is particularly relevant for:

  • Framework/Library Authors: To understand how their reactivity system, state management integration, and rendering pipeline perform under conditions involving complex data relationships and event-driven updates, which are common in modern apps.
  • Developers Building Data-Intensive Applications: Especially those working with:
    • Client-side databases or sync engines: These often involve complex querying and reactive updates from a local data store.
    • Sophisticated state management solutions: Which deal with normalizing data and deriving UI state from multiple sources.
    • Real-time collaborative applications: Where granular, overlapping updates are frequent.
    • Analytics dashboards or admin panels: Which often display multiple views and aggregates over the same core data.
  • Anyone Evaluating Frameworks for Dynamic UIs: To gain insight beyond raw list rendering into how a framework handles the complexity inherent in many real-world applications.

How it Works

  1. In-Memory Data Store: The benchmark uses a normalized, in-memory data store with two primary tables: items and categories, implemented using JavaScript Maps for efficient access.

  2. Reactive Views: Several distinct reactive queries are implemented:

    • Full scan/identity query
    • Dynamic filtering (search text, status)
    • Dynamic sorting by any field
    • Pagination with configurable page size
    • Category-based filtering with joins
    • Combined filters with batched updates
  3. Measurement System:

    • High-precision timing using performance.now()
    • Measures complete reactive cycle including UI updates
    • Tracks operation counts and batch sizes
    • Persistent history using localStorage
    • Interactive results viewer with sorting
  4. Batching Support:

    • Efficient batch processing for data mutations
    • Configurable batch sizes
    • Coalesced updates for better performance

Running the Benchmark

Once the application is running in your browser:

  1. Open your browser's developer console
  2. Use the following commands to run benchmarks:
// Run all benchmark scenarios
window.benchmark.runAll();

// Run a specific scenario with optional batch size
window.benchmark.run("updateSingle", 50);  // Updates 50 items
window.benchmark.run("searchFilter");       // Tests search filtering
window.benchmark.run("sortChange");         // Tests sort operations

// Available scenarios:
- updateSingle      // Single field updates
- updateMultiple    // Multiple field updates
- deleteItems       // Item deletion
- addItems         // Item creation
- searchFilter     // Text search performance
- statusFilter     // Status filtering
- sortChange       // Sort field/direction changes
- pagination       // Page size and navigation
- categoryFilter   // Category-based filtering

// View current results in the UI or check the console output:
// Total time, operation count, and average time per operation

Current Performance Metrics

Query Parameter Operations

Operation Time (ms) Operations Description
Pagination 18.33 25 Page size changes and navigation
Status Filter 29.41 12 Toggle between item statuses
Sort 48.05 24 Field and direction changes
Search 59.69 12 Text-based filtering
Category Filter 212.68 30 Category-based filtering

Data Mutations (Batched)

Operation Time (ms) Operations Description
Update Multiple 108.82 50 Multiple field updates
Update Single 109.46 50 Single field updates
Delete 111.07 50 Item deletion
Add 116.58 50 Item creation

Implementation Details

  1. Reactive System:

    • Uses SolidJS signals and computations
    • Measures complete cycle: event → data change → UI update
    • Supports both individual and batched operations
  2. Data Store:

    • Map-based storage for O(1) lookups
    • Normalized data with item-category relationships
    • Support for CRUD operations and batch updates
  3. Measurement Approach:

    // High-precision timing
    const now = () => performance.now();
    
    // Measure complete reactive cycle
    async function measureReactiveUpdate(action: () => void): Promise<number> {
      await nextFrame(); // Let current cycle complete
      const start = now();
      action();
      await nextFrame(); // Wait for update to process
      const end = now();
      return end - start;
    }
  4. History Tracking:

    • Persistent storage of benchmark results
    • Sortable results table
    • Clear history functionality
    • Tracks operation type, count, timing, and batch size

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages