Benchmarks

What Criogen itself costs, measured as described in design 0014: every model answers at once, so these are the framework's own costs, added on top of a real model's time (typically 0.3–5 s per call). One machine, one run; compare numbers only within this page.

Run of 2026-10-16 on an AMD Ryzen 5 4600H (6 cores / 12 threads), 15 GB RAM, Windows 11, Rust 1.99.0 (release builds), Python 3.13.14, Node 22.14.0, LangGraph 1.2.14. Medians and 95th percentiles of 300–2000 runs after a warm-up.

The Rust engine, agents, storage and gateway#

cargo run -p criogen-bench --release

ScenarioRunsMedian per runp95 per runMedian per unit
workflow: 10 nodes in a row2000214.5 µs325.7 µs21.4 µs per step
workflow: 100 parallel nodes + join500395.6 µs504.0 µs3.9 µs per node
agent: one model call200054.5 µs68.6 µs54.5 µs per run
agent: 10 tool calls + 2 model calls1000505.0 µs626.9 µs505.0 µs per run
thread: send, in memory100074.9 µs129.8 µs74.9 µs per turn
thread: send, SQLite (saved per step)3001.92 ms2.54 ms1.92 ms per turn
model call, direct (baseline)20000.5 µs0.7 µs0.5 µs per call
gateway: chat completion over HTTP2000142.3 µs186.8 µs142.3 µs per request
gateway: streamed chat completion2000219.8 µs306.9 µs219.8 µs per request
  • A conversation turn saved to SQLite costs about 2 ms (several checkpoints per turn, each a committed SQLite transaction); in memory, 75 µs.
  • The gateway adds about 0.14 ms to a request on localhost (0.22 ms streamed), including the HTTP client's own work. Design 0006 §7's target for the translating path is under 3 ms.

The SDK bridges#

python benches/python_bridge.py, node benches/typescript_bridge.mjs

ScenarioRunsMedian per runp95 per run
python: agent run, no tool2000254.8 µs409.1 µs
python: agent run, 1 sync Python tool2000560.0 µs881.2 µs
python: agent run, 1 async Python tool2000717.2 µs1.24 ms
typescript: agent run, no tool2000109.4 µs162.3 µs
typescript: agent run, 1 sync JS tool2000298.8 µs503.1 µs
typescript: agent run, 1 async JS tool2000290.2 µs472.5 µs

Compared with the same run in Rust (54.5 µs), a call from Python costs about 0.2 ms more and from TypeScript about 0.05 ms more. One tool call written in Python adds about 0.3 ms (0.46 ms for an async tool, which runs on the caller's event loop); in JavaScript about 0.19 ms. Both include the extra model call the tool result causes.

The same workflows in LangGraph#

research/.venv/Scripts/python benches/compare_langgraph.py

ScenarioRunsMedian per runp95 per runMedian per unit
workflow: 10 nodes in a row (invoke)20002.44 ms3.56 ms244.4 µs per step
workflow: 10 nodes in a row (ainvoke)20005.19 ms7.29 ms518.8 µs per step
workflow: 100 parallel nodes + join (invoke)50040.28 ms51.18 ms394.9 µs per node
workflow: 100 parallel nodes + join (ainvoke)50034.06 ms44.43 ms333.9 µs per node

With trivial nodes on this machine, Criogen's Rust core spends 21.4 µs per step against LangGraph's 244 µs (invoke), and 3.9 µs per parallel node against 334 µs (ainvoke, LangGraph's faster mode here).

What this does not show: workflows written in Python on Criogen (SDK workflows are not built yet; each node would add roughly the Python bridge cost above), real model latency (which dominates any agent run), or memory use. Once a model takes a second to answer, the difference between 20 µs and 250 µs per step is negligible. It matters for workflows with many steps, wide fan-outs, or many concurrent runs.

Vector search (design 0025)#

cargo run -p criogen-bench --release --bin vectors (same machine, 2026-11-07). 768-dimension vectors, median of the queries.

Memory search without an index (top 5), as the memory store does it:

ItemsIn memorySQLite file
1 0002.8 ms18.0 ms
10 00028.6 ms210 ms
50 000155.9 ms1 278 ms

Collection indexes (-- --indexes --clustered, top 10; vectors gathered around 500 centres, as real embeddings gather around topics):

ItemsFlat buildFlat queryHNSW buildHNSW queryHNSW recall@10
10 0000.04 s2.3 ms7.4 s0.78 ms1.000
50 0000.17 s15.5 ms34.2 s0.24 ms0.980
100 0000.35 s16.6 ms54.4 s0.18 ms0.880

Uniform random vectors (-- --indexes), the worst case for HNSW:

ItemsFlat queryHNSW queryHNSW recall@10
10 0001.8 ms0.80 ms0.342
50 0009.8 ms1.04 ms0.098

Recall is the share of the exact top 10 that HNSW returns. The flat index is exact (recall 1 by definition) and is the default.

Reproducing#

cargo run -p criogen-bench --release
research/.venv/Scripts/python benches/compare_langgraph.py   # needs langgraph
cd sdks/python && maturin develop --release && cd ../.. && python benches/python_bridge.py
bash scripts/test-typescript.sh && node benches/typescript_bridge.mjs   # builds the release addon

Add quick to any of them for a smoke test with fewer runs.