Performance

Headline numbers from the offline benchmark suite at benchmark/. Run locally with:

julia --project=benchmark benchmark/runbench.jl

The full report (benchmark/PERF_REPORT.md) covers methodology, hardware, record-by-record allocation profiles, and a flat profile per hot path.

Read throughput

PathRecords/secAllocationNotes
foreach_record(file, T) do …45 M/sec0.13 bytes/recordTyped callback. Allocation-free hot path.
read_dbn with schema-aware fast path30 M/seclowEager into a typed Vector{T}.
get_range (Historical HTTP, decoded into a DBNStore)~5 M/secmoderateIncludes network + HTTP framing.

For million-record-plus queries, prefer foreach_record over get_range — it streams record-by-record with effectively no GC pressure.

Live throughput

In-process loopback measurements against a mock TCP gateway:

Wire formatRecords/secNotes
Plain DBN8.87 M/secNo zstd; line-rate bound.
zstd-compressed6.16 M/secDecompression on the read side.

These are upper bounds. Real network feeds are typically far slower (the gateway throttles to wire rate) and the bottleneck shifts to the gateway, not the client.

Capture: compression level

stream_to_file and stream_multi_to_files default to compress_level = 1. Empirically L1 is ~35% faster than L3 on the write boundary in exchange for ~15% larger files. For archival captures where storage cost dominates, bump to L3-L9; for low-latency / high-throughput captures keep the default.

Typed channels in Live

Live(...; typed = true) returns concrete-typed channels (Channel{T} per schema) from subscribe!. For the OPRA CMBP-1 replay benchmark this delivers ~25% higher per-cycle throughput over untyped mode. Allocation is roughly equal — Julia's stdlib Channel.put!/take! allocates Condition bookkeeping regardless of element type — so the win is in dispatch, not GC.

When to use what