Benchmark
This page summarizes the benchmark results from the Twilic benchmark harness. Current published SDK measurements use @twilic/core on Node.js 24 (N-API backend) against MessagePack and JSON baselines. v3 schema-aware comparisons must follow the v3 benchmark contract.
For interactive size comparisons in the browser, see the Playground. For quick terminal benchmarks, use twilic bench. For fixture definitions (single-small, batch-homogeneous-256, batch-mixed-256, patch-session), see Benchmark Fixtures.
Setup
The benchmark harness lives in the twilic/benchmark repository. To run it yourself:
git clone https://github.com/twilic/benchmark
cd benchmark
pnpm install
pnpm benchOptions:
pnpm bench -- --backend napi # Node.js N-API (default)
pnpm bench -- --backend wasm # WebAssembly
pnpm bench -- --mode max # maximum benchmark suite
pnpm bench -- --twilic-vs-msgpack-only # hide JSON rows
pnpm bench -- --time-ms 3000 --warmup-ms 1000 # longer windowsWhat Is Measured
| Benchmark | Description |
|---|---|
| Single record encode | Encode one object with a representative schema |
| Single record decode | Decode one Twilic payload |
| 256-record batch encode | Encode 256 same-shape records |
| 256-record batch decode | Decode a 256-record Twilic batch |
| MessagePack encode/decode | Baseline for single and batch |
| JSON stringify/parse | Baseline for single and batch |
| State patch encode | encodePatch on a hot object stream |
| Transport-JSON fast path | encodeTransportJson / decodeToTransportJson |
For v3 Bound and Batch comparisons, reports must disclose whether byte counts include schema id, count, column count, field ids, record framing, compression wrappers, dictionary ids, and dictionary distribution or amortization cost.
Payload Size Comparison
Twilic's size advantage grows with repetition. Representative dynamic results on a 256-record batch with a 6-field object shape:
| Format | Single record (bytes) | 256-record batch (bytes) | Ratio vs JSON |
|---|---|---|---|
| JSON | ~120 | ~30,720 | 1.0× |
| MessagePack | ~80 | ~20,480 | 0.67× |
| Twilic (Dynamic) | ~75 | ~8,960 | 0.29× |
| Twilic (Columnar) | ~70 | ~4,200 | 0.14× |
Numbers are approximate; exact values depend on schema and data distribution.
The key insight: Twilic's advantage is multiplicative at batch scale. Key interning and shape interning eliminate repeated field-name overhead across every record in the batch.
For v3 schema-fixed workloads, compare BOUND_STREAM against schema-shared Protobuf/Avro raw streams and SCHEMA_BATCH against repeated-message or Avro raw-stream baselines under equivalent framing assumptions. Twilic does not claim every arbitrary self-describing payload is smaller than schema-first formats.
Throughput
On a single record, Twilic and MessagePack have comparable throughput — both are significantly faster than JSON parse/stringify. Twilic's overhead vs MessagePack on a single record is encoder state initialization, which is amortized across a batch.
For the N-API backend on Node.js 24, typical throughput:
| Operation | Twilic (N-API) | MessagePack |
|---|---|---|
| Single encode | ~500k ops/s | ~550k ops/s |
| Single decode | ~480k ops/s | ~530k ops/s |
| 256-record batch encode | ~8k batches/s | ~3.5k batches/s |
| 256-record batch decode | ~7.5k batches/s | ~3k batches/s |
Throughput numbers are illustrative; run the harness for your exact hardware.
Max Speed Tips
- Use
--backend napion Node.js (highest throughput) - Use Node.js 24+ (project baseline, JIT-optimized)
- Increase run windows for stability:
--time-ms 3000 --warmup-ms 1000 - For hot paths: pre-serialize once with transport-JSON APIs, then use raw encode methods
- Prefer
SCHEMA_BATCHfor shared-schema tabular datasets; use dynamiccol_batchfor schema-less regular datasets
State Patch Performance
On a hot object stream where 2 of 20 fields change per tick, encodePatch reduces payload size by 85–92% compared to re-encoding the full object. The patch overhead (patch header + changed field encoding) is small relative to the savings.
Running the Full Suite
# Full suite
pnpm bench -- --mode full
# Extended suite with all workloads
pnpm bench -- --mode max
# Twilic vs MessagePack only (no JSON rows)
pnpm bench -- --twilic-vs-msgpack-only
# WASM backend comparison
pnpm bench -- --backend wasm --time-ms 2000Results are printed as formatted CLI tables with throughput (ops/sec) and payload size columns side by side.