Skip to content

Comparison: bunostrdb vs nak vs deed ​

Cross-tool benchmark across ~20 fields: binary size, startup, one-shot commands, streaming throughput, store ingest, query shapes, and memory — nak (Go) and deed (Zig) against bunostrdb (in-process library).

Harness: benches/spark/ (spark.sh drives the CLI tools, spark-bun.ts the library leg). Reproduce with bash benches/spark/spark.sh (or just bench_spark).

Conditions (2026-09-27) ​

  • bunostrdb at ece9b25, native libnostrdb.so built from the pinned submodule (C 9c55578 family).
  • nak: release build from master 91e362b (nak version v0.19.3-248-g91e362b, 33M, Sep 2026).
  • deed 0.3.1, built ReleaseSafe + stripped with pinned Zig 0.16.0.
  • Corpus: 10,000 deterministic signed events from benches/gen-dataset.ts (7,500×kind-1 + 2,500×kind-30023), shared by all three legs.
  • Machine: 12 cores, load average 10–13 during the runs (emulator, Vite, build jobs). Absolute numbers are load-contaminated — read ranges and ordering, not single values. Legs ran sequentially; min–max over 2–4 reps per leg (startup/one-shot best-of-30/50, bunostrdb queries best-of-5, deed --local best-of-30).

A. Size / startup / memory ​

Fieldbunostrdbdeednak
Binarylibnostrdb.so 4.0M + shim 16K (needs Bun runtime)2.5M stripped33M release
version best (median) of 30bun --version 1.22ms (1.50ms); CLI --help spawn ~450ms0.96ms (1.44ms), ~0.3ms own share over /bin/true 0.62ms124ms (133ms)
Peak child RSS, 10k sign/verify (Linux RUSAGE_CHILDREN)—12 / 15M~110 / 111M (--version alone 69M)

B. One-shot commands (best of 50) ​

Fielddeednak
key generate0.73ms131ms (startup floor)
decode npub0.73ms131ms
sign 1 event0.86ms136ms
verify 1 event1.57ms142ms

Every nak one-shot sits on its ~125ms startup floor; the per-op cost only shows in the streaming leg. bunostrdb signs in-process: 0.26–1.25ms per event across reps (800–3,900/s, load-dependent).

C. Streaming throughput (10k records via stdin) ​

Fieldbunostrdbdeednak
sign1.7–5.8k/s (NoteBuilder FFI loop)12–18k/s5.9–6.0k/s
verify— (verify happens at ingest; see D)15–22k/s4.7–5.6k/s
decode npub—~570k/s~60k/s

D. Store ingest (10k events) ​

Fieldbunostrdbdeednak
submit / queue27–88ms batch (processEvents, 113–375k/s)—n/a — no persistent local store (its LMDB backend holds outbox hints/spell cache only)
commit-visible0.22–3.2s (3–45k/s); verify-ON run 2.9s, same band8.0–8.1s (~1.2k/s) via loopback relay.py, each signature checkedclosest analogue: serve + req round-trip (see E)
store fileLMDB 17–21M16M—

Verification cost lands on the ingester threads and overlaps the commit band: skipVerify: true and verify-ON commits fall in the same range on this box.

E. Queries ​

Fieldbunostrdb (in-process, best of 5)deed --local (whole command incl. ~0.9ms startup, best of 30)nak (loopback serve round-trip)
by id0.4–6ms typical (one 110ms outlier under load)0.89ms0.30s
author + kind-1, limit 500.01–0.03ms0.86ms—
kind-1, limit 5000.10–0.17ms2.49ms1.46s
kind-1 all (7.5k), ids1.7–4.8ms21ms full JSON—
kind-1 full JSON19–34ms——
kind-1 count3.8–12.5ms——
tag t= (empty index; corpus has no tags)0.02–0.05msnot measured—
text search benchword (128 cap)0.36–1.8msn/a (no API)n/a
profile lookup (empty)0.12–0.14ms0.85ms—

Takeaways ​

  • nak's cost is process startup: ~125ms per invocation from the release build. Streaming rates (6k sign / 5k verify / 60k decode per s) are its honest per-op numbers.
  • deed owns one-shot and streaming: sub-ms commands, 15–22k verify/s, ~570k decode/s, in a 2.5M binary. Its --local store reads stay tiny whole-command (0.9ms point, 2.5ms/500, 21ms/7.5k).
  • bunostrdb owns in-process queries: 0.01–0.2ms point/author/ capped lookups, 2–5ms id-scan of 7.5k, plus the only text search (~0.5ms). Batch submit is 27–88ms for 10k; the commit band overlaps signature verification either way. Per-event FFI signing is its slowest CPU op next to deed.

Reproduce ​

bash
bash benches/spark/spark.sh   # or: just bench_spark
# Smaller corpus / custom work dir (binaries via env):
N=2000 NAK_BIN=/path/to/nak DEED_BIN=/path/to/deed DEED_RELAY_PY=/path/to/relay.py SPARK_WORK=/tmp/spark bash benches/spark/spark.sh
# Library leg only:
bun benches/spark/spark-bun.ts <events.jsonl> [--verify-on]

Pin notes: deed must be built with its pinned Zig; relay.py ignores the request filter, so the store leg asks for every kind the corpus holds; nak serve needs a few seconds to load the corpus before it listens.

Released under the BSD-3.0 License.