Skip to main content

Performance

Mutative is a high-performance immutable data structure library, it is up to 2x-6x faster than naive handcrafted reducer and up to 16x faster than Immer.

Mutative vs Reducer Performance

Reducer by object

  • Naive handcrafted reducer
// baseState type: Record<string, { value: number }>
const state = {
...baseState,
key0: {
...baseState.key0,
value: i,
},
};
  • Mutative
const state = create(baseState, (draft) => {
draft.key0.value = i;
});

Mutative vs Reducer benchmark by object

Measure(seconds) to update the 1K-100K items object, lower is better(view source).

Mutative is up to 2x faster than naive handcrafted reducer for updating immutable objects.

Reducer by array

  • Naive handcrafted reducer
// baseState type: { value: number }[]

// slower 6x than Mutative
const state = [
{ ...baseState[0], value: i },
...baseState.slice(1, baseState.length),
];

// slower 2.5x than Mutative
// const state = baseState.map((item, index) =>
// index === 0 ? { ...item, value: i } : item
// );

// same performance as Mutative
// const state = [...baseState];
// state[0] = { ...baseState[0], value: i };

The actual difference depends on which spread operation syntax you use.

  • Mutative
const state = create(baseState, (draft) => {
draft[0].value = i;
});

Mutative vs Reducer benchmark by array

Measure(seconds) to update the 1K-100K items array, lower is better(view source).

Mutative is up to 6x faster than naive handcrafted reducer for updating immutable arrays.

Mutative vs Immer Performance

Mutative passed all of Immer's test cases.

Measure(ops/sec) to update 50K arrays and 1K objects, bigger is better(view source). [Mutative v1.0.11 vs Immer v10.1.1]

Benchmark

Naive handcrafted reducer - No Freeze x 4,469 ops/sec ±0.82% (99 runs sampled)
Mutative - No Freeze x 6,015 ops/sec ±1.17% (94 runs sampled)
Immer - No Freeze x 5.36 ops/sec ±0.28% (18 runs sampled)

Mutative - Freeze x 959 ops/sec ±0.90% (99 runs sampled)
Immer - Freeze x 382 ops/sec ±0.53% (94 runs sampled)

Mutative - Patches and No Freeze x 970 ops/sec ±0.99% (96 runs sampled)
Immer - Patches and No Freeze x 5.22 ops/sec ±0.80% (18 runs sampled)

Mutative - Patches and Freeze x 505 ops/sec ±0.85% (93 runs sampled)
Immer - Patches and Freeze x 275 ops/sec ±0.49% (89 runs sampled)

The fastest method is Mutative - No Freeze

Run yarn benchmark to measure performance.

OS: macOS 14.6.1, CPU: Apple M1 Max, Node.js: v20.11.0

Immer relies on auto-freeze to be enabled, if auto-freeze is disabled, Immer will have a huge performance drop and Mutative will have a huge performance lead, especially with large data structures it will have a performance lead of more than 50x.

So if you are using Immer, you will have to enable auto-freeze for performance. Mutative is disabled auto-freeze by default. With the default configuration of both, we can see the 16x performance gap between Mutative (6,015 ops/sec) and Immer (382 ops/sec).

Overall, Mutative has a huge performance lead over Immer in more performance testing scenarios. Run yarn performance to get all the performance results locally.

More Performance Testing Scenarios

Mutative is up to 2.5X-82.9X faster than Immer:

Mutative vs Immer - All benchmark results by average multiplier

view source.