WASM unavailable — WASM bench will be skipped
NXS WAL
click Run benchmark
NXS Fast
click Run benchmark
NXS Sealed
click Run benchmark
NXS WASM
click Run benchmark
JSON NDJSON
click Run benchmark

What each encoder does

Five strategies, same output format — same binary bytes on disk.

EncoderStrategyWhy it matters
NXS WALOne NxsWriter per span. Each call to finish() allocates a chunk array, merges it, and wraps the record in a full preamble + schema + tail-index.Matches a real WAL append where each span is an independent object written to a rolling log. Slow because of per-span allocations and BigInt arithmetic.
NXS FastA single pre-allocated 128-byte Uint8Array is reused for every span. Fields are written with DataView.setUint32 (two calls per i64 — no BigInt). Strings are pre-encoded to Uint8Array once at startup. Only variable offsets are patched per span.Shows the theoretical ceiling of NXS binary encoding in JS: eliminate GC pressure and BigInt. This is what a production WAL writer would look like — fixed schema, typed views, no dynamic allocation in the hot loop.
NXS SealedAll spans written into one shared NxsWriter, then finish() called once. Produces a single .nxb file with one schema header, one preamble, and one tail-index covering all records.The batch/seal path used after WAL rotation. finish() triggers a single large _materialize() merge — fast for the tail-index write but re-encodes every span with BigInt, so throughput is similar to WAL.
NXS WASMA WasmSpanWriter fills a 72-byte input struct in WASM memory via DataView, then calls encode_span(outPtr, fieldsPtr) — a freestanding C function compiled to WASM. Strings are written directly into WASM memory with TextEncoder.encodeInto(). Zero JS allocations per span.Native WASM struct packing with no JS BigInt, no GC pressure, and no per-call memory allocation. The output bytes are a zero-copy view into WASM linear memory. Comparable to NXS Fast — WASM call overhead is the main cost.
JSON NDJSONOne JSON.stringify per span, newline-delimited. IDs are serialised as decimal strings (BigInt cannot be JSON-serialised natively).V8's JSON.stringify is implemented in C++ and highly optimised — it wins on throughput for small objects. But it produces ~2× more bytes because every field name is repeated as a UTF-8 string in every record.

Throughput — spans / second (higher is better)

How many spans each format encodes per second in this browser tab.

NXS WAL
NXS Fast
NXS Sealed
NXS WASM
JSON NDJSON

Output size (smaller is better)

Total bytes produced for all N spans. NXS omits field names and stores numbers in 8-byte binary; JSON repeats every key as a string.

NXS WAL
NXS Fast
NXS Sealed
NXS WASM
JSON NDJSON

Detail

Per-span cost and aggregate metrics for the current run.

Formatns / spanspans / sectotal timeoutput sizebytes / spanvs JSON size
Run the benchmark to see results.
NXS WAL encodes each span independently (append path); NXS Sealed writes all spans then calls finish() once (batch path). NXS WASM calls a native C function compiled to WebAssembly. JSON uses JSON.stringify per span.

Cross-language WAL comparison

NXS WAL append throughput vs each language's standard JSON serialiser — measured at 10,000 spans, Apple M-series (arm64). JS bars update live after each run above.

NXS WAL ns/span (lower is better)

C
run above first

JSON ns/span (lower is better)

C
run above first
Reference numbers from bench_wal.c, bench_wal_test.go, bench_wal.py, ruby/bench_wal.rb, and cargo run --release --bin bench. Rust has no stdlib JSON encoder — only NXS append is shown. JS numbers update live from this browser tab when you run the benchmark.
Benchmark runs entirely in this browser tab — no network, no disk I/O. NXS encoders: /sdk/nxs_writer.js (generic/sealed), hand-rolled DataView (fast), /sdk/wasm.js + /bench/wasm/nxs_reducers.wasm (WASM). JSON via built-in JSON.stringify. Timer: performance.now() (µs resolution). Results vary with browser, hardware, and JIT warm-up state.