SAME DATA. SAME WORK. FOUR REAL IMPLEMENTATIONS.

Watch the difference.
Not a simulation.

Search and chart the same event stream with zerocopy shared snapshots, Immutable.js Lists, Immer arrays, and native arrays. Change one filter. Watch all four paths work.

Preparing this demo…

Generated events only. Two real reader workers per path. No artificial delays, hidden work, or assumed winner.

Ready. No worker is running.
Live —Viewing —Following live data
Answers will be checked against an independent reference.
WITH ZEROCOPY

One shared dataset.

Both readers attach immutable collection roots. Each lookup is local.

Dataset ownerShared roots →Search + summary
Not started
Matching events
—
Query + results
—
Publish + attach
—
Event copies sent
—

No dataset has been sent.

Real timeline counts appear here.

EventServiceMessage
Load all four paths to compare their answers.
Inspect selected event
Select an event row.
IMMUTABLE.JS

Immutable.js Lists.

Two readers keep real persistent Lists. Batched deltas update live roots; earlier roots stay readable.

Dataset ownerCloned columns →Search + summary
Not started
Matching events
—
Query + results
—
Publish + attach
—
Event copies sent
—

No dataset has been sent.

Real timeline counts appear here.

EventServiceMessage
Load all four paths to compare their answers.
Inspect selected event
Select an event row.
IMMER

Immer arrays.

Two readers keep frozen arrays. Batched produce appends create new roots; earlier roots stay readable.

Dataset ownerCloned columns →Search + summary
Not started
Matching events
—
Query + results
—
Publish + attach
—
Event copies sent
—

No dataset has been sent.

Real timeline counts appear here.

EventServiceMessage
Load all four paths to compare their answers.
Inspect selected event
Select an event row.
WITHOUT ZEROCOPY · NATIVE

A dataset per reader.

Both readers use native arrays. By default, updates clone only new events.

Dataset ownerCloned columns →Search + summary
Not started
Matching events
—
Query + results
—
Publish + attach
—
Event copies sent
—

No dataset has been sent.

Real timeline counts appear here.

EventServiceMessage
Load all four paths to compare their answers.
Inspect selected event
Select an event row.
50 results per page on each path.
WHAT CHANGES

Same answer.
Different data movement.

The copy counter counts logical event deliveries to reader workers, not bytes or measured heap. Loading 100,000 events into two readers sends 200,000 event copies per replica path. Shared mode sends memory handles and root descriptors, not cloned event records.

Queries return small result pages in all paths. Those replies, local decoded strings, wrappers, caches, and allocations still have a cost. Zero event copies does not mean zero allocation or zero messages.

Each library gets a fair implementation.

All four paths use the same five primitive columns and search functions. Immutable.js uses real Lists and batched withMutations appends. Queries read Lists directly, with no toJS() conversion. Immer uses native arrays and batched produce appends with default auto-freezing. The default sends only incremental deltas to all three replica paths; full replication is an optional baseline.

Immutable.js shares structure between versions within each worker. It does not share that JavaScript heap across workers. Publication includes plain-column encoding, structured clone, and List reconstruction in each reader. Immer structured-clones its arrays, then freezes the full replica or appends the delta with produce in each reader. Freezing and reader-side updates are included in publication. Changed arrays copy on write within each worker; Immer does not share their backing storage across workers. Freeze retains actual Immer, Immutable.js, and zerocopy roots. Native arrays retain a prefix length for this append-only workload.

Live timings are observations, not a speed claim.

The paths run concurrently and can compete for CPU. Timings separate publication/attachment and queries. Dataset construction and owner-side append work are not in those numbers. Startup and rendering are excluded. Results are checked after timing.

Construction times appear after loading.

Run the controlled four-architecture benchmark →

Session limit: 200,000 events. Stop terminates the coordinator and its reader workers. No forced garbage collection. Logs demonstrate a general pattern for editors, tables, catalogs, graphs, and simulations. Explore use cases → · Open the full explorer →

Immer was not measured in the recorded Node.js memory results below. Those historical figures are separate from this live four-path comparison.

RECORDED MEMORY · NOT A LIVE BROWSER METER

Count the memory, too.

100,000 events. One owner and two readers for Shared, Immutable.js and Native replicas. One native owner has no reader replicas. Compare retained data with total process RAM. Each graph has its own labelled, zero-based scale. The full table below shows post-query retained data memory, in MiB. Lower is better.

Less data memory across two readersUnique messages · 100,000 events · after queriesRecorded Node.js · MiB · lower is better

Retained data memory

zerocopy9.10 MiB
Immutable.js44.46 MiB
Native replicas33.36 MiB
One native owner14.04 MiB

Shared WASM capacity is counted once. Includes caches and spare capacity; excludes the empty-worker baseline. Replicated paths: one owner + two readers. One native owner: no reader replicas.

Exact values and trial range

Median and observed min–max of three fresh processes. These ranges are not confidence intervals.

Design · readersMedian (MiB)Trial range (MiB)
zerocopy · 2 readers9.109.09–9.10
Immutable.js · 2 readers44.4644.27–44.55
Native replicas · 2 readers33.3633.36–33.36
One native owner · 0 readers14.0414.04–14.05

10 October 2026 · Node v22.23.3 · linux x64 · 3 trials per case. Not browser RAM.
Open SVG · Download chart data

The whole process tells a different storyUnique messages · 100,000 events · after queriesRecorded Node.js · MiB · lower is better

Total process RAM (RSS)

zerocopy122.06 MiB
Immutable.js212.99 MiB
Native replicas164.17 MiB
One native owner116.21 MiB

Absolute resident set size (RSS), including workers and runtime overhead. One native owner uses the least RSS in this run. Replicated paths: one owner + two readers. One native owner: no reader replicas.

Exact values and trial range

Median and observed min–max of three fresh processes. These ranges are not confidence intervals.

Design · readersMedian (MiB)Trial range (MiB)
zerocopy · 2 readers122.06119.30–122.42
Immutable.js · 2 readers212.99206.97–216.69
Native replicas · 2 readers164.17163.95–164.23
One native owner · 0 readers116.21114.78–117.30

10 October 2026 · Node v22.23.3 · linux x64 · 3 trials per case. Not browser RAM.
Open SVG · Download chart data

Node.js worker measurements · median of three fresh processes · 10 October 2026
InputSharedImmutable.jsNative replicasOne native owner
Repeated messages4.7033.7723.356.06
Unique messages9.1044.4633.3614.04
20% Unicode prefix9.7946.6535.8614.88

Includes every worker's JavaScript heap change, tracked buffers, caches, and current shared WASM capacity counted once. Excludes the empty-worker baseline. These are Node.js measurements, not measurements of this device or browser. The live event selector does not change this table.

Total process RAM gives a different result: the one-native-owner control uses the least RSS in this run. Read the full report for RSS, peak process RAM, reader scaling, old snapshots and limits.

Read the memory comparison and method →

Type a topic to find a guide.

↓ ↑ to move · Enter to open · Esc to close

Browse documentation →