# keys (and values) — benchmark

Workload: 10_000 rows; tick inserts one row at a fresh key. Batch streams
1000 inserts. Generated by [comparisons/bench/operators/keys.bench.ts](../../comparisons/bench/operators/keys.bench.ts).

| Library | Setup (ms) | Single (ms) | vs data | Batch 1000 (ms) | vs data |
|---|---:|---:|---:|---:|---:|
| **data** | 1.62 | **0.020** | — | **2.15** | — |
| solid | 1.02 | 0.163 | 8.2× | 235.84 | 110× |
| rxjs | 1.09 | 0.170 | 8.5× | 286.58 | 133× |
| svelte-store | 1.11 | 0.174 | 8.7× | 402.14 | 187× |
| preact-signals | 1.43 | 0.239 | 11.9× | 208.33 | 96.9× |
| react | 1.73 | 0.316 | 15.8× | 555.61 | 258× |
| mobx | 172.40 | 4.32 | 216× | 4198.39 | 1953× |
| vue-reactivity | 12.06 | 7.07 | 354× | 16385.94 | 7621× |



data is fastest on both single (5.1x over svelte-store) and batch
(225x over solid).

## How

[index.ts](index.ts) maintains a single output array. BI0 appends the
new names (for `keys`) or values (for `values`) — incremental, no
rebuild. Removes / updates / XU0 rebuild from scratch because
reverse-mapping a name to its output index is O(N) without a parallel
`name→index` map. Adding that map is straightforward when a remove-heavy
workload appears.

Run `BENCH_OPS=keys npm run bench:ops` to refresh — update this file when
the numbers change materially.
