Change language
Get Started

Benchmarks

Measured, not claimed.

Release build on macOS arm64 · 10 cores · 16 × ~2047 KB files. All scenarios are offline — no network, no LLM — so they run in CI.

Tool dispatch overhead

How much machinery sits between the LLM's tool call and the actual work.

MeasurementIterationsPer-call
registry.execute (raw dispatch)3005140 µs
execute_batch, 1 call3007614 µs
execute_batch, 8 calls (amortized)3205893 µs
ToolCall args serde round-trip100000752 ns

Executor overhead over raw dispatch: 2473 µs per single-call batch; amortized overhead drops to 753 µs per call in an 8-call batch.

Parallel vs sequential — I/O-bound

16 × file_read of distinct ~2047 KB files.

sequential
79.0 ms
1.00×
join_all
83.7 ms
0.94×
spawn (tokio)
25.8 ms
3.06×
execute_batch_spawnsequential / join_all

16/16 calls succeeded (join_all), 16/16 (spawn); all classified parallel-safe.

Parallel vs sequential — CPU-bound

8 × parse_html of a ~1 MB table (3000 rows), selector `tr.item`, texts mode.

sequential
130.3 ms
1.00×
join_all
72.4 ms
1.80×
spawn (tokio)
34.5 ms
3.78×

join_all shares one thread — spawn spreads CPU work across cores.

Mixed batch — automatic partitioning

A realistic agent turn: reads (parallel-safe) + writes (sequential) in one batch. 5 ran concurrently, 3 serialized; total 70.9 ms, 8 succeeded. Order preserved.

ToolPhaseSuccessDuration
file_read (r0)parallel16 ms
file_read (r1)parallel20 ms
file_read (r2)parallel25 ms
file_read (r3)parallel29 ms
file_write (w0)sequential2 ms
file_write (w1)sequential0 ms
file_write (w2)sequential0 ms
grep (g0)parallel65 ms

parse_html scaling with document size

Same selector (`tr.item`, texts mode), increasing document sizes. Up to 531k rows/s.

DocumentRowsAvg parseThroughput
6 KB1000.19 ms531,915 rows/s
63 KB10004.08 ms245,339 rows/s
191 KB30009.55 ms314,268 rows/s
773 KB1200034.22 ms350,723 rows/s

extract_json throughput

~4 MB JSON document with 20,000 objects. Stateless & parallel-safe (re-parsed per call).

QueryIterationsAvg
wildcard scan `items[*].value` (limit 500)1071.24 ms
deep single key `items.12345.meta.score`1067.78 ms
top-level key `total`1043.47 ms

web_feed (quick-xml) — scaling & parallelism

Local RSS fixture; tolerance to feed size and CPU-bound speed under parallelism. Up to 1.1M items/s.

Feed itemsAvg parseItems/s
10000.93 ms1,077,586
50004.78 ms1,045,588
1200010.81 ms1,110,391
2000027.10 ms738,089
sequential
236.2 ms
1.00×
spawn
188.6 ms
1.25×

8 × web_feed of a ~5 MB feed; 8/8 succeeded both modes.

code_symbols / repo_map — symbol extraction

240 Rust files (~14 KB each, 40 fns + 40 structs + impls per file).

ToolModeWall timeItems
code_symbolssingle7.2 ms7007 lines
repo_mapsingle34.2 ms4330 lines
sequential
61.9 ms
1.00×
join_all
32.6 ms
1.90×
spawn
20.4 ms
3.04×

8/8 symbol scans succeeded (join_all), 8/8 (spawn).

Semantic memory — absorb / search / digest

Offline TF-IDF embedder (no network, no LLM); in-memory SQLite.

BatchAbsorbedWall timePer fact
101010.2 ms1020 µs
100899.4 ms94 µs
50033582.6 ms165 µs

Re-absorbing 100 known facts: 93 skipped, 0 created in 5.1 ms (dedup fast path).

Hybrid search (vector + BM25)MatchesMedian
Acme revenue units filing52.30 ms
Globex churn rate report51.62 ms
headcount in Kazan during 202252.23 ms
Initech margin units51.95 ms
support load Dubai filing51.66 ms
Store sizeFill timeSearch (median)
1000 memories53 ms5.28 ms
5000 memories926 ms23.52 ms
10000 memories828 ms47.47 ms

Digest build (relevant + TODOs + recent): 4 relevant memories in 4.76 ms.

Reproduce

cargo build --release
./target/release/parallel-research bench --scenario all > bench.md
# individual scenarios: dispatch | parallel-io | parallel-cpu | mixed |
#                       parse-scale | extract-json | feed-parse | code-map | memory
./target/release/parallel-research stats -o <output-dir>   # p50/p95 per tool

Benchmarks use no network and no LLM (offline TF-IDF embedder) — runnable in CI. Numbers above are a snapshot on macOS arm64 (10 cores), release build.

Field notes: 31× on repo_map

Benchmarks are how we catch regressions — and how we find wins. Profiling repo_map revealed a silently-serialized regex pass; moving it to a OnceLock-cached compiler took it from 902 ms to 29.5 ms (31×). The same audit unlocked 3.12× / 5.16× on web_feed and code_symbols under execute_batch_spawn.