strawmANN benchmark report

strawmANN against Qdrant · AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M (24 logical) · generated 2026-10-13 00:02:06 CEST

Dataset
sift1m
Vectors
1,000,000 × 128 · 10,000 held-out queries
Metric
euclid
Storage datatype
strawmANN float32 · Qdrant float32 (default)
Quantization
none (fp32) · separate rows measure binary (1 bit/dim), PQ (product), SQ8 scalar, turboquant
strawmANN: 55/55 ok Qdrant: 55/55 ok

Summary

At equal recall, strawmANN serves 1.34x to 2.40x Qdrant's throughput. That range spans the recall levels measured; allowing for the uncertainty in each recall figure widens it to 0.97x to 2.69x.

throughput at equal recall
1.34 to 2.40x
strawmANN over Qdrant, recall@10 0.908 to 0.998
p99 latency at 90% load
strawmANN1.11 ms
Qdrant4.49 ms
W4-sat90, open loop, one offered rate
upload and index build
strawmANN42 s
Qdrant70 s
W1 + W2
peak memory (RSS)
strawmANN4.7 GiB
Qdrant5.2 GiB
largest before the concurrent-write rows (W11); of it, anonymous 2.2 GiB / 872.4 MiB
written to disk
strawmANN5.4 GiB
Qdrant28.4 GiB
before the concurrent-write rows (W11); they wrote 122.4 MiB / 10.6 GiB more

Throughput against recall

Read it vertically: at any recall both engines reach, the higher curve is faster. Throughput from bfb W10, recall from the conformance sweep, joined on ef. ef is the same unit here: Qdrant held 2 segments for this run, one populated and 1 empty (read back per segment from the engine), and strawmANN held one graph, so equal ef is equal traversal width and the curves may be read at equal x. That is a property of this run, not of the engines.

Every figure is the median of 3 passes per engine, run alternately (A/B/A/B). What this does not establish.

Glossary
recall@10
Of the ten nearest neighbours a query really has, the share the engine returned. 1.0 is a perfect answer. "Really has" is settled by an exhaustive fp64 search, not by the other engine.
ef
The candidate-list size: how many nodes the index keeps in play while searching. Larger is slower and more accurate. It does not mean the same amount of work in both engines, which is why the headline holds recall fixed instead.
MRDE
Mean relative distance error: when the engine returns a wrong neighbour, how much further away it is than the right one. Small numbers mean the misses were near-misses.
qps
Queries per second. On a batched row one request carries several queries, and the request rate is shown under it.
p50 / p99 / p99.9
The latency half of requests beat, that 99% beat, that 99.9% beat. The tail is what a user notices.
closed / open loop
A closed loop sends the next request only when the last one comes back, so a slow server receives less work and its tail looks better than it is. An open loop sends at a fixed rate regardless.
noise floor
How much a number moves between identical runs on this machine. A ratio inside it is shown grey with ≈: no measured difference. Hover a ratio to see its band.
conformance tier
What the two engines were shown to agree on before any speed was quoted. T1 licenses a single engine's own numbers; T3 licenses comparing the two, and requires their recall to be statistically indistinguishable.
§ numbers
Sections of docs/spec.md, the written rule each claim in the appendix is measured against. §7.1 is the host gate, §7.4 the comparison rules, §8 what may be published.

Throughput

Queries per second; higher is better. The ratio is strawmANN over Qdrant: green is faster, red slower, grey ≈ inside the noise floor (hover a ratio for its band). A dash means the pair is not compared, and the note says why. An ef sweep is one row showing its range; every measurement is under All throughput rows.

workloadstrawmANNQdrantrationotes
W3search, fp32, single query2,1422,0131.06x
W4search, saturating (closed loop)27,94714,226-one pass apart: strawmANN pass 1 -14%
W5search batched (16 distinct dataset queries per request)28,1561,826 requests/s17,2171,148 requests/s1.64x
W6quantized: scalar33,45518,9031.77x
W6 ef 32 to 512SQ8 recall control (latency only)9,151 to 77,3457,164 to 38,7801.28 to 2.02x
W7quantized: binary + oversampling27,30619,742-recall below the usable floor: 0.0650 and 0.0658, both under 0.50 — this row characterises the encoding, not the engines
W7-2bitquantized: binary quantization, 2 bits + oversampling31,40517,623-recall differs: 0.5452 vs 0.5026
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling30,52317,280-recall below the usable floor: 0.3817 and 0.3428, both under 0.50 — this row characterises the encoding, not the engines
W8quantized: PQ27,15319,2401.41x
W14-1bitquantized: TurboQuant, 1 bit + oversampling27,33116,257-recall differs: 0.7628 vs 0.7158
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling24,87315,866-recall differs: 0.8526 vs 0.8147
W14-2bitquantized: TurboQuant, 2 bits + oversampling24,91916,951-recall differs: 0.9711 vs 0.9427
W14-4bitquantized: TurboQuant, 4 bits + oversampling31,60718,6671.69x
W9exact / brute force1911231.56x
W10 ef 32 to 512recall control (latency only)7,434 to 47,0503,964 to 22,2161.88 to 2.38x
W12-sel1filtered search, one keyword (~1% of bench12)36,26918,3591.98x
W12-sel10filtered search, any of 10 keywords (~10% of bench12)4,9342,1842.26x
W12-sel1 ef 32 to 512filtered recall control, one keyword (latency only)36,226 to 36,52820,773 to 20,9441.74 to 1.75x
W12-sel10 ef 32 to 512filtered recall control, any of 10 keywords (latency only)4,907 to 14,9461,605 to 2,5882.26 to 3.53x1 of 5 points not compared recall differs
W13scroll / pagination56,64150,4921.12xstrawmANN: 91% is client and socket, not server Qdrant: 81% is client and socket, not server
W11-steadymixed read/write below the rebuild threshold: search bench2 while 50,000 synthetic points append21,6244,481-search-during-write; no recall join
W11mixed read/write: search bench2 while 200,000 synthetic points append (runs last)17,8002,017-search-during-write; no recall join

Throughput by workload

Higher is better. Hatched bars are rows the table does not compare (W4, W7, W11): each bar is that engine's own rate, and the pair is not a result.

Recall

recall@10 against an exact fp64 search, not against the other engine. Equal ef is not equal work in the two engines, so the comparison that counts holds recall fixed and compares throughput there.

At matched recall

recall@10measured atstrawmANN q/sQdrant q/sstrawmANN / Qdrantrange over recall CI
0.9077strawmANN at ef=32, Qdrant interpolated47,05021,0422.24x2.15 – 2.32x
0.9605Qdrant at ef=64, strawmANN interpolated36,78415,6612.35x2.30 – 2.40x
0.9625strawmANN at ef=64, Qdrant interpolated36,44715,1842.40x2.23 – 2.58x
0.9872strawmANN at ef=128, Qdrant interpolated24,26910,3082.35x2.24 – 2.48x
0.9879Qdrant at ef=128, strawmANN interpolated23,28910,2052.28x1.94 – 2.69x
0.9956strawmANN at ef=256, Qdrant interpolated14,1187,0402.01x1.81 – 2.22x
0.9967Qdrant at ef=256, strawmANN interpolated10,0716,6831.51x1.03 – 2.20x
0.9977strawmANN at ef=512, Qdrant interpolated7,4345,5331.34x0.97 – 1.85x
How this is computed

Interpolated linear in log(q/s) between the two bracketing measurements, nothing extrapolated past the measured range. Throughput is bfb's W10 sweep, recall the conformance sweep, joined on ef — same m and ef_construct, but separate builds, so the pairing assumes two builds with identical parameters are equivalent.

The last column is why the ratio is not a result on its own. The ratio treats the anchor's recall as exact; it is an estimate, and moving it across its 95% interval moves the interpolated rate with it — near the top of the sweep 0.003 of recall spans a factor of 1.8, so two decimals there quote the interpolation. Even that is the narrow reading: it moves one recall and not the other, adjacent anchors share bracketing segments, and the throughputs behind it are medians of the run's passes.

At matched recall, SQ8

The same reading over the scalar-quantized collection. Under the `pool` policy both engines rescore `ef` candidates, so W6 is compared row by row as well; held at equal recall, the reading does not depend on the rows landing in one recall band. Note where each engine's curve stops, because a recall only one of them reaches is the more useful fact about an encoding than any ratio.

recall@10measured atstrawmANN q/sQdrant q/sstrawmANN / Qdrantrange over recall CI
0.9092strawmANN at ef=32, Qdrant interpolated77,34537,2572.08x2.02 – 2.13x
0.9603Qdrant at ef=64, strawmANN interpolated61,88130,0912.06x2.02 – 2.10x
0.9640strawmANN at ef=64, Qdrant interpolated60,90628,4972.14x1.99 – 2.29x
0.9876Qdrant at ef=128, strawmANN interpolated34,47420,0241.72x1.63 – 1.82x
0.9888strawmANN at ef=128, Qdrant interpolated33,45918,7261.79x1.49 – 2.14x
0.9968Qdrant at ef=256, strawmANN interpolated18,44212,1611.52x1.38 – 1.66x
0.9974strawmANN at ef=256, Qdrant interpolated17,62210,6931.65x1.00 – 2.72x
0.9993Qdrant at ef=512, strawmANN interpolated9,8227,1641.37x1.14 – 1.65x
How this is computed

Interpolated linear in log(q/s) between the two bracketing measurements, nothing extrapolated past the measured range. Throughput is bfb's W6 sweep, recall the conformance sweep, joined on ef — same m and ef_construct, but separate builds, so the pairing assumes two builds with identical parameters are equivalent.

The last column reads as it does in the fp32 table above.

At matched recall, filtered to 10%

The same reading under a keyword filter over the points the condition matched, 20,088 to 20,287 across 3 builds in strawmANN and 20,131 to 20,215 across 3 builds in Qdrant (bfb draws the keyword payloads unseeded at each upload). The per-row table compares W12-sel10 at the one ef it measures; held at equal recall, the comparison extends to every recall both engines reach. Note the shape rather than any single number: one engine's curve is flat in ef and the other's is steep, so where you match decides the ratio.

recall@10measured atstrawmANN q/sQdrant q/sstrawmANN / Qdrantrange over recall CI
0.9784strawmANN at ef=32, Qdrant interpolated14,9462,5045.97x5.92 – 6.02x
0.9915Qdrant at ef=64, strawmANN interpolated9,6992,4204.01x3.72 – 4.32x
0.9953strawmANN at ef=64, Qdrant interpolated8,5472,2783.75x3.66 – 3.85x
0.9982Qdrant at ef=128, strawmANN interpolated6,1122,1782.81x2.51 – 3.13x
0.9996Qdrant at ef=256, strawmANN interpolated5,1441,9082.70x2.54 – 2.86x
0.9999Qdrant at ef=512, strawmANN interpolated4,9711,6053.10x2.98 – 3.21x
How this is computed

Interpolated linear in log(q/s) between the two bracketing measurements, nothing extrapolated past the measured range. Throughput is bfb's W12-sel10 sweep, recall the conformance sweep, joined on ef — same m and ef_construct, but separate builds, so the pairing assumes two builds with identical parameters are equivalent.

The last column reads as it does in the fp32 table above.

Recall by ef

efstrawmANNQdrant
recall@1recall@10recall@100MRDErecall@1recall@10recall@100MRDE
ef=320.94540.9077-3.19e-030.93670.8979-3.51e-03
ef=640.97910.9625-1.18e-030.97590.9605-1.22e-03
ef=1280.99400.98720.94924.59e-040.99370.98790.94373.15e-04
ef=2560.99780.99560.98392.56e-040.99880.99670.98337.75e-05
ef=5120.99840.99770.99502.13e-040.99980.99940.99611.08e-05
How recall was measured

10,000 held-out queries, limit 10, ε=4.172e-07, against the fp64 oracle rather than against the other engine. Base checksum 7bf7ead7809a45cd: the same corpus the latency rows were measured on. Each pass rebuilds the collection. Across 3 independent builds of it, recall@10 at ef=512 spread by: strawmANN 0.00192; Qdrant 0.00022. strawmANN's graphs disagree with each other 9x as much as Qdrant's do, so a ratio read at the top of this table reports which graph the build produced as much as which engine built it. Over the same builds the engine reported unreachable nodes: strawmANN 0 of 200,000 and 0 of 1,000,000 — a node nothing points at is invisible at any ef, so that is where a graph-quality difference shows rather than being inferred from the recall beside it. Level seed: strawmANN 0x57ea3111. Recorded as provenance: under this engine's level draw, six builds at four seeds sit within 0.00003 of recall@10 at ef 512, well inside the spread above.

What each quantization costs in recall

Colour is the encoding here, not the engine — the engines are the line style. Each sweep is joined on the quantization parameters it actually sent, so a curve speaks only for the search its row ran. Higher is better, and the encodings are not free: read this against the throughput their rows bought.

Latency

Client-side round trip. A closed loop understates the tail (a stalled server stops receiving requests), so this keeps the fixed-rate, open-loop rows, which offer the same load to both engines, plus single-client W3 and batched W5. Every row is under All latency rows.

workloadstrawmANNQdrant
p50p99p99.9p50p99p99.9
W3 search, fp32, single query473 µs547 µs607 µs500 µs607 µs762 µs
W4-sat50 search, fixed rate at 50% of saturation (open loop)401 µs705 µs874 µs738 µs1.79 ms2.20 ms
W4-sat70 search, fixed rate at 70% of saturation (open loop)496 µs947 µs1.10 ms822 µs1.98 ms2.87 ms
W4-sat90 search, fixed rate at 90% of saturation (open loop)563 µs1.11 ms1.23 ms1.18 ms4.49 ms8.34 ms
W5 search batched (16 distinct dataset queries per request)36.08 ms37.03 ms53.77 ms57.74 ms98.66 ms116.90 ms

Ingest and index build

Qdrant indexes while it ingests, so its upload time already contains most of the indexing; strawmANN uploads raw and builds afterwards. Compare the sum, not the upload line.

Where the load time goes

Solid is upload, hatched is the wait for Green. The bar's whole length is the sum this section asks you to compare; the split is why the upload line alone is not comparable between these engines.

workloadstrawmANNQdrant
W0-uploadd=4 floor: graph traversal with the distance taken out19.06 s22.05 s
W1ingest throughput (no index wait)1.10 s11.98 s
W2index build, time to Green41.13 s58.14 s
W6-uploadsearch, SQ8 scalar quantization40.13 s47.12 s
W7-uploadsearch, binary quantization41.13 s49.11 s
W7-2bit-uploadsearch, binary quantization43.14 s47.10 s
W7-1p5bit-uploadsearch, binary quantization43.13 s52.12 s
W8-uploadsearch, product quantization51.16 s89.22 s
W14-1bit-uploadupload41.14 s53.13 s
W14-1p5bit-uploadupload41.14 s65.16 s
W14-2bit-uploadupload41.14 s63.14 s
W14-4bit-uploadupload41.14 s58.14 s
W12-uploadupload9.03 s14.04 s
W1 + W2upload and index, together42.2 s70.1 s1.66x

Memory and disk

What each engine held in memory and moved to and from disk over the whole run. Per-row figures are under Storage and I/O.

strawmANNQdrant
storage on disk3.1 GiBallocated at --capacity2.9 GiB
peak memory (RSS)4.7 GiB5.2 GiB
read from disk48.0 KiB3.2 GiB
written to disk5.4 GiB28.4 GiB

Peak memory and storage on disk are read before the concurrent-write rows (W11): an engine rewriting segments maps old and new files at once, and RSS counts each mapping. Bytes written are summed over the same rows, since W11's volume is set by the harness's write rate; the other disk figures are totals over every row.

Appendix

How the run was set up, every row of every table, and the diagnostics behind them. Charts on a logarithmic axis say so on the axis: read the positions there, not the distances.

Run conditions and conformance

Measured as-deployed: the scheduler was left as it ships, so a difference is what a user would see rather than the engine in isolation, and ambient load is part of the measurement. Qdrant ran equal-work: asked for one populated graph (--segments 1), as strawmANN serves, so ef means the same thing on both sides. This is the configuration §8's comparative licensing is built around, and it is a control rather than a deployment. Its optimizer treats the count as a target; what it actually held is read back from the engine and stated under Collection config.

Conformance tier reached: T4 quantization fidelity. T1 passed, so single-engine performance rows are licensed (§8). T3 passed, so a strawmANN-vs-Qdrant throughput comparison is licensed: the engines are at equal recall (§7.4). Conformance hash fec450c094fe8321.

On exact search the two engines' scores differ by at most 0.000e+00 (p99 0.000e+00), against a calibrated relative ε of 4.172e-07. §8.1: bit-exactness is unachievable between two different summation orders, so this — equal values within a measured tolerance — is the claim the speed rests on.

The conformance harness's single-client rate agrees on the ordering (4.10x to 4.47x); a different instrument, so no ratio is formed from it.

Every figure is the median of 3 passes per row per engine, alternated A/B/A/B (§7.4), and the spread is this run's own over 42 of 55 rows. The ingest and index-build rows (W0-upload, W1, W2, W6-upload, W7-upload, W7-2bit-upload, W7-1p5bit-upload, W8-upload, W14-1bit-upload, W14-1p5bit-upload, W14-2bit-upload, W14-4bit-upload, W12-upload) have none, so no build time carries a verdict. Each pass rebuilds the index, so the bands include build variance and are wider than a floor measured against one standing graph.

Units are queries per second. bfb reports rps, which counts batch requests: at --search-batch-size 16 the two differ by 16x, and reading one as the other once turned a 2.2x speedup into an apparent 7x regression. The tables show the request rate wherever it diverges.

The open-loop rows are not a speed. W4-sat50/70/90 offer a fixed fraction of measured saturation; serving it means the engine kept up, not that it was faster, so no ratio is printed. They exist because --parallel is a closed loop, where a stalled server stops receiving requests and understates its own tail.

ef is the same unit here: Qdrant held 2 segments for this run, one populated and 1 empty (read back per segment from the engine), and strawmANN held one graph, so equal ef is equal traversal width and the curves may be read at equal x. That is a property of this run, not of the engines.

What was measured builds, dataset, host
strawmANN
sm-sift-perf-1012
Qdrant
qd-sift-perf-1012
enginecommit e292f0b4651a
ReleaseFast, native build, vnni on
binary sha256 d6f453ebe3803da4
built 2026-10-12T13:37:51Z with zig 0.16.0
version 1.19.2-dev
binary ~/.cache/strawmann/qdrant-dbeb0f73/qdrant
sha256 dbeb0f73dea2d371 build 878843e6 (from the server's banner, not a checkout)
native binary outside a checkout: sha256 is the identity (§8.9)
network native no container in the path, like strawmann
measured2026-10-12T18:29:11Z to 2026-10-12T21:15:35Z (3 passes)2026-10-12T18:58:59Z to 2026-10-12T21:53:32Z (3 passes)
profileas-deployed · both engines
§7.1 gatepass · both engines
environment hash373e8531fd3d1bf6 · both engines
load generatorbfb dev @ 96fd5f0 (qdrant/bfb#188; #187's dependency update on top of #186, BM25 k/b in qdrant#11012's nested params, #185's text requests and #172, findings 32's --rps reaping fix) · both engines
clientqdrant-client 1.16.1-dev (git dev branch) · both engines
launched as~/Workspace/strawmann/zig-out/bin/strawmann --port 6334 --capacity 1250000 --connections 64 --workers 7 --io-threads 1 --pin --cpus 4-11 --data-dir ~/.cache/strawmann/strawmann-storage --default-placement cached~/.cache/strawmann/qdrant-dbeb0f73/qdrant
cores the engine could use4-11 (8 cores) requested by the harness
4-11 (8 cores) observed on 8 threads
0-23 (24 cores) observed on 1 thread
4-11 (8 cores) requested by the harness
4-11 (8 cores) observed on 42 threads

Dataset

sift1m, 1000000 × 128, euclid, 10000 held-out queries
ground truth: shipped, and diffed against our fp64 recompute
1 file, each pinned by sha256 in datasets.json

Host

AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M
24 logical cores · 58.6 GB · kernel 7.0.0-38-generic
memory bandwidth: 73.6 GB/s aggregate (24 threads) · 44.8 GB/s single core (61% of bus)
strawmann startup banner, 2026-10-12T18:29:11Z; the Qdrant run agrees within 10%
All throughput rows every measurement, with its notes
workloadstrawmANNQdrantrationotes
W0d=4 floor: graph traversal with the distance taken out4,5183,3361.35x1.35x is 1.84x less work per query x 0.68x cores busy during the row (0.69 against 1.01) x 1.00x clock x 1.08x counted on-CPU share: the middle term is occupancy, not search speed d=4 floor: this measures graph traversal and heaps with the distance taken out, not request plumbing (findings 28: 76% of the server's CPU was HNSW search, 24% kernel; the RPC path is a small remainder)
W3search, fp32, single query2,1422,0131.06x
W4search, saturating (closed loop)27,94714,226-strawmANN pass 1 -14% against two passes that agree: one pass set the spread on this row, so a band built from it is not a noise band
W4-sat50search, fixed rate at 50% of saturation (open loop)7,1097,109offered
W4-sat70search, fixed rate at 70% of saturation (open loop)9,9529,952offered
W4-sat90search, fixed rate at 90% of saturation (open loop)12,79512,795offered
W5search batched (16 distinct dataset queries per request)28,1561,826 requests/s17,2171,148 requests/s1.64xstrawmANN: per-batch latency (16 queries/request); queries: dataset, random-sample; -n 100000 (2x the table's 50000) Qdrant: per-batch latency (16 queries/request); queries: dataset, random-sample batched 16, so qps and rps differ by 16x; the ratio uses qps
W6quantized: scalar33,45518,9031.77xstrawmANN: -n 100000 (2x the table's 50000)
W6-ef32SQ8 recall control, ef=32 (latency only)77,34538,7801.99xstrawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000) strawmANN: 0.46 ms of the client's 0.53 ms p50 is not server time (7x), so 85% of this row is the load generator and the socket
W6-ef64SQ8 recall control, ef=64 (latency only)60,90630,0912.02xstrawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000)
W6-ef128SQ8 recall control, ef=128 (latency only)33,45920,0241.67xstrawmANN: -n 100000 (2x the table's 50000)
W6-ef256SQ8 recall control, ef=256 (latency only)17,62212,1611.45x
W6-ef512SQ8 recall control, ef=512 (latency only)9,1517,1641.28x
W7quantized: binary + oversampling27,30619,742-strawmANN: -n 100000 (2x the table's 50000) recall below the usable floor: 0.0650 and 0.0658, both under 0.50 — this row characterises the encoding, not the engines
W7-2bitquantized: binary quantization, 2 bits + oversampling31,40517,623-strawmANN: -n 100000 (2x the table's 50000) recall unequal: 0.5452 vs 0.5026; §7.4 compares at equal recall; the rescore pools match, so the encoders differ
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling30,52317,280-strawmANN: -n 100000 (2x the table's 50000) recall below the usable floor: 0.3817 and 0.3428, both under 0.50 — this row characterises the encoding, not the engines
W8quantized: PQ27,15319,2401.41xstrawmANN: -n 100000 (2x the table's 50000)
W14-1bitquantized: TurboQuant, 1 bit + oversampling27,33116,257-strawmANN: -n 100000 (2x the table's 50000) recall unequal: 0.7628 vs 0.7158; §7.4 compares at equal recall; the rescore pools match, so the encoders differ
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling24,87315,866-recall unequal: 0.8526 vs 0.8147; §7.4 compares at equal recall; the rescore pools match, so the encoders differ
W14-2bitquantized: TurboQuant, 2 bits + oversampling24,91916,951-recall unequal: 0.9711 vs 0.9427; §7.4 compares at equal recall; the rescore pools match, so the encoders differ
W14-4bitquantized: TurboQuant, 4 bits + oversampling31,60718,6671.69xstrawmANN: -n 100000 (2x the table's 50000)
W9exact / brute force1911231.56xbrute force over the whole collection, no index involved
W10-ef32recall control, ef=32 (latency only)47,05022,2162.12xstrawmANN: -n 100000 (2x the table's 50000)
W10-ef64recall control, ef=64 (latency only)36,44715,6612.33xstrawmANN: -n 100000 (2x the table's 50000)
W10-ef128recall control, ef=128 (latency only)24,26910,2052.38x
W10-ef256recall control, ef=256 (latency only)14,1186,6832.11x
W10-ef512recall control, ef=512 (latency only)7,4343,9641.88x
W12-sel1filtered search, one keyword (~1% of bench12)36,26918,3591.98xstrawmANN: -n 100000 (2x the table's 50000) filtered search over a keyword payload index both engines were asked to build; whether each did is read back from the engine and refused beside the row when it did not. Recall is measured under the filter, against ground truth restricted to the matching set
W12-sel10filtered search, any of 10 keywords (~10% of bench12)4,9342,1842.26xfiltered search over a keyword payload index both engines were asked to build; whether each did is read back from the engine and refused beside the row when it did not. Recall is measured under the filter, against ground truth restricted to the matching set
W12-sel1-ef32filtered recall control, one keyword, ef=32 (latency only)36,22620,7731.74xstrawmANN: -n 100000 (2x the table's 50000)
W12-sel1-ef64filtered recall control, one keyword, ef=64 (latency only)36,52820,9441.74xstrawmANN: -n 100000 (2x the table's 50000)
W12-sel1-ef128filtered recall control, one keyword, ef=128 (latency only)36,39120,8271.75xstrawmANN: -n 100000 (2x the table's 50000)
W12-sel1-ef256filtered recall control, one keyword, ef=256 (latency only)36,47920,9151.74xstrawmANN: -n 100000 (2x the table's 50000)
W12-sel1-ef512filtered recall control, one keyword, ef=512 (latency only)36,40520,8761.74xstrawmANN: -n 100000 (2x the table's 50000)
W12-sel10-ef32filtered recall control, any of 10 keywords, ef=32 (latency only)14,9462,588-recall unequal: 0.9784 vs 0.9656; §7.4 compares at equal recall
W12-sel10-ef64filtered recall control, any of 10 keywords, ef=64 (latency only)8,5472,4203.53x
W12-sel10-ef128filtered recall control, any of 10 keywords, ef=128 (latency only)4,9302,1782.26x
W12-sel10-ef256filtered recall control, any of 10 keywords, ef=256 (latency only)4,9361,9082.59x
W12-sel10-ef512filtered recall control, any of 10 keywords, ef=512 (latency only)4,9071,6053.06x
W13scroll / pagination56,64150,4921.12x-n 200000 (4x the table's 50000) strawmANN: 0.12 ms of the client's 0.13 ms p50 is not server time (12x), so 91% of this row is the load generator and the socket Qdrant: 0.12 ms of the client's 0.15 ms p50 is not server time (5x), so 81% of this row is the load generator and the socket 1.12x is 3.40x less work per query x 0.33x cores busy during the row (1.46 against 4.48) x 1.00x clock x 1.01x counted on-CPU share: the middle term is occupancy, not search speed
W11-steadymixed read/write below the rebuild threshold: search bench2 while 50,000 synthetic points append21,6244,481-strawmANN: qps over the 25.0 s of the append the search saw (22,171 over the whole search); append 2,000 points/s Qdrant: qps over the 25.0 s of the append the search saw (4,484 over the whole search); append 2,000 points/s search-during-write; no recall join
W11mixed read/write: search bench2 while 200,000 synthetic points append (runs last)17,8002,017-strawmANN: qps over the 60.6 s of the append the search saw (19,108 over the whole search); append 3,300 points/s Qdrant: qps over the 60.6 s of the append the search saw (2,106 over the whole search); append 3,300 points/s search-during-write; no recall join

W10: throughput against ef

ef is the same unit here: Qdrant held 2 segments for this run, one populated and 1 empty (read back per segment from the engine), and strawmANN held one graph, so equal ef is equal traversal width and the curves may be read at equal x. That is a property of this run, not of the engines.
All latency rows closed loop included, p50 to max

A row flagged “… not server time” is one where the client saw far more than the server reported: below the rate at which a queue can form, what is left is the load generator's own scheduling.

workloadstrawmANN p50strawmANN p95strawmANN p99strawmANN p99.9strawmANN maxQdrant p50Qdrant p95Qdrant p99Qdrant p99.9Qdrant max
W0d=4 floor: graph traversal with the distance taken out closed loop 219 µs235 µs251 µs295 µs1.30 ms297 µs328 µs359 µs407 µs2.79 ms
W3search, fp32, single query closed loop 473 µs523 µs547 µs607 µs1.25 ms500 µs572 µs607 µs762 µs1.99 ms
W4search, saturating (closed loop) closed loop 2.28 ms2.46 ms2.53 ms20.33 ms24.34 ms4.02 ms8.77 ms12.31 ms22.15 ms27.98 ms
W4-sat50search, fixed rate at 50% of saturation (open loop) open loop 401 µs626 µs705 µs874 µs1.84 ms738 µs1.34 ms1.79 ms2.20 ms5.13 ms
W4-sat70search, fixed rate at 70% of saturation (open loop) open loop 496 µs869 µs947 µs1.10 ms3.98 ms822 µs1.61 ms1.98 ms2.87 ms10.80 ms
W4-sat90search, fixed rate at 90% of saturation (open loop) open loop 563 µs896 µs1.11 ms1.23 ms3.28 ms1.18 ms2.71 ms4.49 ms8.34 ms16.79 ms
W5search batched (16 distinct dataset queries per request) closed loop 36.08 ms36.45 ms37.03 ms53.77 ms57.65 ms57.74 ms84.50 ms98.66 ms116.90 ms134.48 ms
W6quantized: scalar closed loop 1.91 ms2.02 ms2.07 ms2.76 ms21.00 ms2.96 ms6.68 ms9.33 ms23.34 ms33.40 ms
W6-ef32SQ8 recall control, ef=32 (latency only) closed loop 533 µs1.07 ms1.41 ms1.98 ms14.08 ms1.48 ms3.02 ms3.93 ms5.61 ms20.12 ms
W6-ef64SQ8 recall control, ef=64 (latency only) closed loop 1.00 ms1.30 ms1.51 ms2.13 ms24.61 ms1.91 ms3.93 ms5.36 ms8.46 ms21.63 ms
W6-ef128SQ8 recall control, ef=128 (latency only) closed loop 1.91 ms2.02 ms2.07 ms2.88 ms21.51 ms2.98 ms4.95 ms6.50 ms22.86 ms29.84 ms
W6-ef256SQ8 recall control, ef=256 (latency only) closed loop 3.64 ms3.85 ms3.94 ms20.52 ms24.68 ms5.07 ms7.55 ms9.26 ms21.82 ms29.41 ms
W6-ef512SQ8 recall control, ef=512 (latency only) closed loop 7.04 ms7.48 ms7.67 ms14.93 ms22.25 ms8.92 ms10.11 ms11.93 ms21.60 ms29.50 ms
W7quantized: binary + oversampling closed loop 2.33 ms2.46 ms2.52 ms2.67 ms18.32 ms3.09 ms5.01 ms6.53 ms18.21 ms25.19 ms
W7-2bitquantized: binary quantization, 2 bits + oversampling closed loop 2.03 ms2.12 ms2.16 ms2.54 ms31.05 ms3.11 ms7.44 ms10.83 ms22.41 ms32.80 ms
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling closed loop 2.08 ms2.18 ms2.23 ms2.56 ms23.41 ms3.16 ms7.64 ms10.86 ms23.06 ms33.03 ms
W8quantized: PQ closed loop 2.36 ms2.49 ms2.54 ms2.77 ms18.46 ms3.19 ms5.11 ms6.68 ms23.63 ms28.79 ms
W14-1bitquantized: TurboQuant, 1 bit + oversampling closed loop 2.34 ms2.48 ms2.53 ms3.03 ms18.10 ms3.34 ms8.27 ms11.85 ms19.70 ms34.82 ms
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling closed loop 2.57 ms2.72 ms2.78 ms18.12 ms21.11 ms3.44 ms8.46 ms11.97 ms23.89 ms36.52 ms
W14-2bitquantized: TurboQuant, 2 bits + oversampling closed loop 2.57 ms2.75 ms2.82 ms16.94 ms19.55 ms3.21 ms7.79 ms11.03 ms24.24 ms34.98 ms
W14-4bitquantized: TurboQuant, 4 bits + oversampling closed loop 2.03 ms2.14 ms2.19 ms2.65 ms19.71 ms3.01 ms6.80 ms9.44 ms14.22 ms19.06 ms
W9exact / brute force closed loop 37.34 ms60.74 ms68.90 ms75.30 ms84.38 ms65.78 ms73.15 ms77.33 ms83.35 ms85.07 ms
W10-ef32recall control, ef=32 (latency only) closed loop 163 µs197 µs221 µs309 µs1.33 ms333 µs532 µs652 µs856 µs2.17 ms
W10-ef64recall control, ef=64 (latency only) closed loop 215 µs250 µs271 µs396 µs1.52 ms471 µs773 µs957 µs1.24 ms3.26 ms
W10-ef128recall control, ef=128 (latency only) closed loop 328 µs377 µs403 µs735 µs1.89 ms708 µs1.27 ms1.52 ms1.95 ms3.39 ms
W10-ef256recall control, ef=256 (latency only) closed loop 569 µs677 µs743 µs882 µs3.15 ms1.07 ms1.92 ms2.30 ms3.01 ms4.71 ms
W10-ef512recall control, ef=512 (latency only) closed loop 1.08 ms1.35 ms1.52 ms1.73 ms4.47 ms1.85 ms3.19 ms3.72 ms4.75 ms7.71 ms
W12-sel1filtered search, one keyword (~1% of bench12) closed loop 1.73 ms1.85 ms2.43 ms3.03 ms20.09 ms3.21 ms6.39 ms8.32 ms25.38 ms33.24 ms
W12-sel10filtered search, any of 10 keywords (~10% of bench12) closed loop 12.74 ms14.10 ms14.38 ms26.36 ms36.19 ms28.87 ms34.08 ms45.06 ms61.57 ms77.11 ms
W12-sel1-ef32filtered recall control, one keyword, ef=32 (latency only) closed loop 1.74 ms1.86 ms1.93 ms3.08 ms25.67 ms2.88 ms4.95 ms6.40 ms23.43 ms29.47 ms
W12-sel1-ef64filtered recall control, one keyword, ef=64 (latency only) closed loop 1.73 ms1.82 ms1.90 ms2.79 ms19.57 ms2.85 ms4.94 ms6.36 ms20.14 ms26.99 ms
W12-sel1-ef128filtered recall control, one keyword, ef=128 (latency only) closed loop 1.73 ms1.82 ms1.90 ms3.10 ms23.34 ms2.87 ms4.93 ms6.41 ms23.64 ms33.41 ms
W12-sel1-ef256filtered recall control, one keyword, ef=256 (latency only) closed loop 1.73 ms1.82 ms1.90 ms2.89 ms22.78 ms2.87 ms4.93 ms6.39 ms22.63 ms28.76 ms
W12-sel1-ef512filtered recall control, one keyword, ef=512 (latency only) closed loop 1.73 ms1.82 ms1.90 ms3.01 ms20.92 ms2.87 ms4.90 ms6.35 ms18.56 ms27.31 ms
W12-sel10-ef32filtered recall control, any of 10 keywords, ef=32 (latency only) closed loop 4.27 ms4.46 ms4.56 ms21.44 ms26.44 ms24.72 ms26.81 ms27.92 ms36.85 ms53.32 ms
W12-sel10-ef64filtered recall control, any of 10 keywords, ef=64 (latency only) closed loop 7.50 ms7.89 ms8.04 ms24.43 ms30.90 ms26.24 ms28.54 ms29.92 ms37.34 ms51.10 ms
W12-sel10-ef128filtered recall control, any of 10 keywords, ef=128 (latency only) closed loop 12.75 ms14.10 ms14.27 ms28.53 ms38.15 ms29.01 ms33.04 ms35.07 ms46.94 ms62.77 ms
W12-sel10-ef256filtered recall control, any of 10 keywords, ef=256 (latency only) closed loop 12.74 ms14.10 ms14.25 ms24.12 ms35.00 ms32.89 ms40.01 ms42.94 ms51.42 ms66.94 ms
W12-sel10-ef512filtered recall control, any of 10 keywords, ef=512 (latency only) closed loop 12.81 ms14.14 ms14.33 ms24.78 ms34.28 ms38.82 ms50.57 ms54.30 ms59.87 ms81.80 ms
W13scroll / pagination closed loop 127 µs184 µs205 µs238 µs1.03 ms146 µs210 µs292 µs459 µs1.76 ms
W11-steadymixed read/write below the rebuild threshold: search bench2 while 50,000 synthetic points append closed loop 329 µs393 µs1.95 ms2.93 ms9.68 ms1.51 ms3.48 ms6.72 ms13.70 ms34.82 ms
W11mixed read/write: search bench2 while 200,000 synthetic points append (runs last) closed loop 333 µs967 µs2.00 ms3.20 ms9.42 ms2.77 ms10.56 ms16.97 ms26.23 ms836.66 ms
Storage and I/O block layer and syscalls, per row

The syscall rows count every descriptor, sockets included, so on a search row they measure the network rather than the disk.

strawmANNQdrant
storage on disk3.1 GiBbefore W11-steady, W11allocated at --capacity2.9 GiBbefore W11-steady, W11
peak RSS4.7 GiB10.7 GiB5.2 GiB before the writers
of which anonymous2.2 GiB1.2 GiB872.4 MiB before the writers
of which file-backed2.2 GiB9.1 GiB3.7 GiB before the writers
disk read bytes48.0 KiB3.2 GiB
disk write bytes5.5 GiB39.1 GiB
disk read ops3682,824
disk write ops83,653700,693
syscall reads (all fds)21,367,51275,363
syscall writes (all fds)11,500,8187,592,439

measured via strawmANN: proc+cgroup / Qdrant: proc+cgroup. proc supplies syscall counts and block-layer bytes, cgroup supplies block-layer operations and bytes, so a row one interface does not carry reads n/a via …. unknown means it was not measured, and 0 means it was: an engine started with no --data-dir has no store, which is the row this section exists for. storage on disk is the level before the rows with a concurrent writer: during those an engine that rewrites segments is caught mid-rewrite, and the same row has read 3.47 and 10.11 GiB on two runs of one binary. peak RSS does include them, being a peak.

Per workload

A search row doing block-layer reads is an engine going to disk to answer a query.

workloadstrawmANN readstrawmANN writtenstrawmANN read opsstrawmANN write opsQdrant readQdrant writtenQdrant read opsQdrant write ops
W0-upload4.0 KiB61.1 MiB3987129.5 MiB401.2 MiB3,3338,523
W000030006
W10488.4 MiB0013.2 MiB1.6 GiB43525,591
W20488.4 MiB07,883168.1 MiB2.3 GiB4,23641,775
W300030006
W400000000
W4-sat5000000000
W4-sat7000000000
W4-sat9000000000
W500000000
W6-upload4.0 KiB488.4 MiB37,881167.1 MiB2.7 GiB4,22147,760
W600000000
W6-ef3200000000
W6-ef6400030000
W6-ef12800000000
W6-ef25600000000
W6-ef51200000000
W7-upload12.0 KiB488.4 MiB97,881189.4 MiB2.6 GiB4,75847,500
W700000000
W7-2bit-upload0488.4 MiB07,882189.0 MiB2.5 GiB4,74345,340
W7-2bit00000000
W7-1p5bit-upload0488.4 MiB07,880208.8 MiB2.7 GiB5,22348,729
W7-1p5bit00000000
W8-upload12.0 KiB488.4 MiB98,059145.1 MiB2.2 GiB3,60338,797
W800000000
W14-1bit-upload0488.4 MiB07,880186.0 MiB2.5 GiB4,65344,655
W14-1bit00000000
W14-1p5bit-upload0488.4 MiB07,880211.3 MiB2.7 GiB5,27748,960
W14-1p5bit00000000
W14-2bit-upload0488.4 MiB07,880218.9 MiB2.8 GiB5,46051,042
W14-2bit00000000
W14-4bit-upload0488.4 MiB07,883193.3 MiB2.9 GiB4,85752,096
W14-4bit00000000
W900000000
W10-ef3200000000
W10-ef6400000000
W10-ef12800000000
W10-ef25600000000
W10-ef51200000000
W12-upload16.0 KiB97.8 MiB12046.3 MiB585.8 MiB1,32311,434
W12-sel10001,5770000
W12-sel1000000000
W12-sel1-ef3200030000
W12-sel1-ef6400000000
W12-sel1-ef12800000000
W12-sel1-ef25600000000
W12-sel1-ef51200000000
W12-sel10-ef3200000000
W12-sel10-ef6400000000
W12-sel10-ef12800000000
W12-sel10-ef25600000000
W12-sel10-ef51200000000
W1300000000
W11-steady024.5 MiB0415519.6 MiB4.6 GiB12,74179,872
W11097.9 MiB01,673730.1 MiB6.1 GiB17,961108,607
Scheduler and memory CPU use, run-queue wait, migrations

Whether the engine was running while it ran. of wall is CPU over elapsed, waiting is runnable-but-not-scheduled, migrations checks the pinning claim, and switches gives voluntary over involuntary — the scheduler taking the core away against the engine choosing to sleep, which per unit of work is the cheapest signal of lock contention there is. A dash is not a zero: an index build's threads exit before the row does, and threads shows what fraction of the row the survivors account for.

Time spent waiting for a core

Lower is better; the bar between a pair is the gap.

Peak memory per row

Peak RSS while the row ran, from the engine's own process. Unlike the disk counters this is not refused across the two engines: residency decides where bytes live, and this is what the process held either way.

workloadstrawmANNQdrant
cpuof wallwaitingswitches vol/involmigrationsfaults min/majthreadscpuof wallwaitingswitches vol/involmigrationsfaults min/majthreads
W0-upload126.7 s567%59.6 ms39,300 / 6236114,484 / 09 1%160.3 s510%13,962.1 ms155,560 / 30,29513,395417,441 / 196,55541 8%
W08.0 s72%2.4 ms150,106 / 3900 / 0915.5 s103%3.4 ms543,567 / 17195509 / 037 0%
W12.2 s68%2.1 ms122,590 / 20160,271 / 0977.4 s550%27,567.8 ms133,407 / 41,33314,995207,287 / 261,47452 0%
W2305.5 s689%136.4 ms128,011 / 1,4115228,003 / 09 1%440.3 s609%33,352.1 ms138,867 / 52,17115,658485,870 / 288,65739 4%
W319.9 s85%2.2 ms152,398 / 2304 / 0925.7 s103%3.4 ms549,226 / 48209509 / 039 0%
W413.6 s743%0.9 ms41,626 / 22070 / 0927.4 s773%77,428.7 ms65,597 / 44,56616,3982,030 / 076
W4-sat5060.5 s214%2.9 ms299,343 / 44012 / 09119.3 s422%125,171.7 ms1,117,480 / 159,394371,235269 / 068 95%
W4-sat7058.3 s288%13.7 ms218,532 / 46034 / 09120.3 s595%168,810.7 ms1,040,417 / 211,890370,251333 / 068
W4-sat9057.9 s367%1.1 ms188,630 / 40020 / 09106.6 s677%109,704.2 ms496,140 / 123,070148,7831,118 / 044 0%
W525.0 s701%1.0 ms12,834 / 400147 / 0922.7 s777%71,874.4 ms4,422 / 9,7531,78638,695 / 076
W6-upload299.7 s685%111.0 ms47,703 / 1,3270277,753 / 09 1%328.6 s556%22,398.0 ms152,023 / 35,86415,672561,106 / 304,99840 0%
W622.8 s747%2.2 ms73,613 / 32010 / 0920.4 s762%68,753.5 ms76,796 / 47,92215,3981,773 / 072
W6-ef3215.6 s576%2.0 ms106,848 / 15090 / 0919.7 s745%47,775.6 ms191,494 / 74,32823,599470 / 078 93%
W6-ef6425.5 s747%1.4 ms47,526 / 40044 / 0925.6 s756%56,843.6 ms126,566 / 57,76618,043122 / 078
W6-ef12822.8 s747%1.0 ms72,518 / 2000 / 0918.7 s739%10,640.3 ms29,420 / 10,1496,029111 / 078
W6-ef25621.0 s729%0.9 ms62,574 / 2700 / 0931.8 s765%13,088.6 ms34,831 / 16,6746,239523 / 046 0%
W6-ef51239.6 s719%1.8 ms78,174 / 5403 / 0955.6 s792%12,144.6 ms32,461 / 26,0741,080386 / 046
W7-upload305.1 s681%114.5 ms48,976 / 1,4411247,541 / 09 1%349.8 s565%19,990.3 ms148,311 / 34,34418,496556,124 / 319,18943 0%
W727.8 s743%2.3 ms92,756 / 4200 / 0919.2 s745%10,017.6 ms27,194 / 9,8944,9161,773 / 051
W7-2bit-upload306.0 s654%114.5 ms50,144 / 1,4631247,485 / 09 1%320.2 s526%20,986.5 ms145,547 / 35,27617,320507,387 / 312,80347 6%
W7-2bit24.2 s743%2.0 ms80,505 / 3200 / 0921.9 s762%74,642.5 ms73,996 / 48,64115,5792,152 / 078
W7-1p5bit-upload306.0 s654%122.2 ms48,487 / 1,4782247,481 / 09 1%380.6 s567%21,732.9 ms146,844 / 37,38118,167562,838 / 321,98847 6%
W7-1p5bit24.9 s745%2.1 ms83,266 / 3200 / 0922.4 s765%76,285.0 ms72,795 / 50,36416,5292,376 / 078
W8-upload388.8 s708%139.9 ms48,173 / 1,7541249,660 / 09 0%566.7 s572%10,648.1 ms2,150,775 / 75,27558,586462,533 / 240,64343 1%
W827.9 s743%1.5 ms94,652 / 3300 / 0919.6 s745%9,938.6 ms26,520 / 10,2755,0411,508 / 051
W14-1bit-upload307.4 s687%116.1 ms47,215 / 1,4301237,464 / 09 1%377.5 s554%22,320.0 ms154,362 / 37,38615,969518,202 / 312,76648 6%
W14-1bit27.6 s740%1.4 ms95,889 / 3300 / 0923.8 s766%81,501.1 ms69,084 / 46,20616,3892,706 / 079
W14-1p5bit-upload309.3 s690%117.4 ms48,487 / 1,4191240,046 / 09 1%459.4 s565%27,703.1 ms154,932 / 45,94317,037582,138 / 324,36247 5%
W14-1p5bit15.1 s736%1.0 ms49,356 / 1100 / 0924.5 s768%84,236.3 ms67,292 / 46,06315,9113,270 / 079
W14-2bit-upload308.6 s688%120.5 ms49,647 / 1,4200242,873 / 09 1%433.2 s549%26,059.5 ms161,679 / 44,68018,325630,285 / 326,61747 4%
W14-2bit15.1 s735%0.8 ms52,687 / 1600 / 0922.8 s765%78,044.7 ms69,158 / 47,58116,4943,445 / 078
W14-4bit-upload309.1 s690%118.6 ms50,140 / 1,4562253,711 / 09 1%382.7 s515%21,608.1 ms172,982 / 41,38518,796637,899 / 334,33346 7%
W14-4bit24.1 s746%1.2 ms78,329 / 2300 / 0920.8 s764%69,510.8 ms78,427 / 51,51217,3901,912 / 078
W972.7 s694%4.6 ms3,239 / 13000 / 09127.3 s780%9,492.0 ms18,131 / 9,2046,902153 / 049
W10-ef329.9 s452%3.2 ms137,890 / 1100 / 0913.1 s573%5,140.2 ms222,947 / 18,48362,1291,042 / 049
W10-ef6415.8 s562%1.2 ms163,283 / 600 / 0919.1 s593%11,902.7 ms264,838 / 33,915107,170836 / 074
W10-ef12813.6 s648%0.7 ms95,046 / 400 / 0929.4 s595%22,235.9 ms285,802 / 35,787105,602153 / 076
W10-ef25624.7 s692%1.1 ms102,259 / 1100 / 0946.5 s619%34,252.2 ms295,359 / 37,108127,521104 / 068
W10-ef51247.6 s703%2.3 ms114,308 / 3800 / 0980.5 s636%51,040.1 ms316,096 / 44,310157,882289 / 069
W12-upload48.7 s416%18.6 ms10,676 / 2270117,259 / 09 1%82.4 s436%4,943.4 ms34,561 / 9,0435,065163,649 / 189,40152 0%
W12-sel121.2 s748%3.6 ms63,889 / 340138 / 0921.1 s763%65,654.2 ms107,255 / 67,01422,4491,639 / 084
W12-sel1071.8 s706%12.3 ms46,554 / 9102 / 09182.9 s798%99,290.4 ms44,804 / 47,4982,8086,252 / 059 0%
W12-sel1-ef3221.1 s748%1.3 ms61,036 / 2304 / 0918.3 s750%12,271.2 ms24,934 / 9,9585,383296 / 059
W12-sel1-ef6421.0 s749%1.1 ms61,265 / 2800 / 0918.1 s748%12,168.3 ms24,850 / 9,5594,95036 / 059
W12-sel1-ef12821.0 s748%1.2 ms63,893 / 2400 / 0918.1 s744%12,120.3 ms24,922 / 9,5764,911115 / 059
W12-sel1-ef25621.0 s746%1.1 ms63,195 / 2100 / 0918.2 s748%12,139.7 ms24,191 / 9,4744,97789 / 059
W12-sel1-ef51221.0 s746%0.9 ms64,730 / 1700 / 0918.1 s745%12,046.5 ms24,851 / 9,3655,05923 / 059
W12-sel10-ef3224.6 s727%1.0 ms76,497 / 2200 / 09154.2 s796%26,205.4 ms40,246 / 37,6793261,613 / 059
W12-sel10-ef6442.3 s718%2.1 ms96,750 / 3300 / 09165.2 s798%27,344.5 ms41,163 / 39,2283071,921 / 059
W12-sel10-ef12871.9 s706%2.4 ms46,640 / 7400 / 09183.5 s798%29,547.8 ms43,218 / 41,9293911,575 / 059
W12-sel10-ef25671.8 s706%2.6 ms45,939 / 9500 / 09209.6 s799%32,082.7 ms47,191 / 45,1264902,883 / 059
W12-sel10-ef51272.2 s706%2.8 ms45,764 / 8700 / 09249.2 s799%36,426.6 ms52,516 / 50,5704562,994 / 059
W135.3 s144%2.2 ms229,052 / 800 / 0918.0 s442%2,194.2 ms737,256 / 14,115230,194440 / 076
W11-steady210.3 s639%12,368.5 ms1,287,096 / 2,386541,162,430 / 09 90%230.0 s725%152,429.9 ms728,581 / 219,500243,5631,194,422 / 261,04559 83%
W11517.5 s656%71,348.8 ms2,646,385 / 11,7542248,099,839 / 09 77%577.2 s758%437,856.7 ms836,931 / 402,610248,3761,708,094 / 405,98065 72%
Waiting and stalls where the time went when the engine was not running

waiting is runnable and not scheduled, blocked on disk is not runnable at all, and pressure is PSI for the engine's cgroup (some = at least one task stalled, full = every runnable task).

Time stalled on I/O

Time every task in the engine's cgroup was stalled on I/O. Lower is better. 39 rows never stalled on I/O and are not drawn.

workloadstrawmANNQdrant
waitingblocked on diskcpu some/fullio some/fullmemory some/fullwaitingblocked on diskcpu some/fullio some/fullmemory some/full
W0-upload59.6 ms0 ms15 / 8 ms38 / 38 ms0 / 0 ms13,962.1 ms0 ms1,298 / 17 ms35 / 31 ms0 / 0 ms
W02.4 ms0 ms43 / 43 ms0 / 0 ms0 / 0 ms3.4 ms0 ms74 / 74 ms0 / 0 ms0 / 0 ms
W12.1 ms0 ms10 / 10 ms8 / 8 ms0 / 0 ms27,567.8 ms0 ms2,334 / 13 ms43 / 27 ms0 / 0 ms
W2136.4 ms0 ms31 / 13 ms1 / 1 ms0 / 0 ms33,352.1 ms0 ms2,781 / 20 ms141 / 128 ms0 / 0 ms
W32.2 ms0 ms44 / 44 ms0 / 0 ms0 / 0 ms3.4 ms0 ms79 / 79 ms0 / 0 ms0 / 0 ms
W40.9 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms77,428.7 ms0 ms2,888 / 3 ms0 / 0 ms0 / 0 ms
W4-sat502.9 ms0 ms63 / 63 ms0 / 0 ms0 / 0 ms125,171.7 ms0 ms8,198 / 87 ms0 / 0 ms0 / 0 ms
W4-sat7013.7 ms0 ms40 / 40 ms0 / 0 ms0 / 0 ms168,810.7 ms0 ms9,466 / 62 ms0 / 0 ms0 / 0 ms
W4-sat901.1 ms0 ms31 / 31 ms0 / 0 ms0 / 0 ms109,704.2 ms0 ms7,053 / 33 ms0 / 0 ms0 / 0 ms
W51.0 ms0 ms0 / 0 ms0 / 0 ms0 / 0 ms71,874.4 ms0 ms2,746 / 1 ms0 / 0 ms0 / 0 ms
W6-upload111.0 ms0 ms21 / 9 ms1 / 1 ms0 / 0 ms22,398.0 ms0 ms1,906 / 21 ms318 / 302 ms0 / 0 ms
W62.2 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms68,753.5 ms0 ms2,416 / 2 ms0 / 0 ms0 / 0 ms
W6-ef322.0 ms0 ms9 / 9 ms0 / 0 ms0 / 0 ms47,775.6 ms0 ms2,079 / 4 ms0 / 0 ms0 / 0 ms
W6-ef641.4 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms56,843.6 ms0 ms2,574 / 4 ms0 / 0 ms0 / 0 ms
W6-ef1281.0 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms10,640.3 ms0 ms1,153 / 2 ms0 / 0 ms0 / 0 ms
W6-ef2560.9 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms13,088.6 ms0 ms1,430 / 2 ms0 / 0 ms0 / 0 ms
W6-ef5121.8 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms12,144.6 ms0 ms1,415 / 1 ms0 / 0 ms0 / 0 ms
W7-upload114.5 ms0 ms21 / 9 ms40 / 40 ms0 / 0 ms19,990.3 ms0 ms1,722 / 23 ms176 / 159 ms0 / 0 ms
W72.3 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms10,017.6 ms0 ms1,083 / 2 ms0 / 0 ms0 / 0 ms
W7-2bit-upload114.5 ms0 ms22 / 10 ms1 / 1 ms0 / 0 ms20,986.5 ms0 ms1,785 / 22 ms182 / 159 ms0 / 0 ms
W7-2bit2.0 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms74,642.5 ms0 ms2,608 / 2 ms0 / 0 ms0 / 0 ms
W7-1p5bit-upload122.2 ms0 ms26 / 10 ms1 / 1 ms0 / 0 ms21,732.9 ms0 ms1,887 / 23 ms217 / 206 ms0 / 0 ms
W7-1p5bit2.1 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms76,285.0 ms0 ms2,672 / 2 ms0 / 0 ms0 / 0 ms
W8-upload139.9 ms0 ms25 / 10 ms10 / 10 ms0 / 0 ms10,648.1 ms0 ms1,884 / 166 ms119 / 113 ms0 / 0 ms
W81.5 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms9,938.6 ms0 ms1,070 / 2 ms0 / 0 ms0 / 0 ms
W14-1bit-upload116.1 ms0 ms22 / 10 ms1 / 1 ms0 / 0 ms22,320.0 ms0 ms1,931 / 25 ms207 / 195 ms0 / 0 ms
W14-1bit1.4 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms81,501.1 ms0 ms2,840 / 3 ms0 / 0 ms0 / 0 ms
W14-1p5bit-upload117.4 ms0 ms22 / 10 ms1 / 1 ms0 / 0 ms27,703.1 ms0 ms2,386 / 26 ms153 / 143 ms0 / 0 ms
W14-1p5bit1.0 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms84,236.3 ms0 ms2,924 / 2 ms0 / 0 ms0 / 0 ms
W14-2bit-upload120.5 ms0 ms22 / 10 ms2 / 2 ms0 / 0 ms26,059.5 ms0 ms2,192 / 27 ms237 / 202 ms0 / 0 ms
W14-2bit0.8 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms78,044.7 ms0 ms2,719 / 2 ms0 / 0 ms0 / 0 ms
W14-4bit-upload118.6 ms0 ms22 / 9 ms1 / 1 ms0 / 0 ms21,608.1 ms0 ms1,900 / 31 ms228 / 215 ms0 / 0 ms
W14-4bit1.2 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms69,510.8 ms0 ms2,462 / 2 ms0 / 0 ms0 / 0 ms
W94.6 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms9,492.0 ms0 ms1,051 / 15 ms0 / 0 ms0 / 0 ms
W10-ef323.2 ms0 ms12 / 12 ms0 / 0 ms0 / 0 ms5,140.2 ms0 ms584 / 15 ms0 / 0 ms0 / 0 ms
W10-ef641.2 ms0 ms13 / 13 ms0 / 0 ms0 / 0 ms11,902.7 ms0 ms1,080 / 16 ms0 / 0 ms0 / 0 ms
W10-ef1280.7 ms0 ms6 / 6 ms0 / 0 ms0 / 0 ms22,235.9 ms0 ms1,856 / 19 ms0 / 0 ms0 / 0 ms
W10-ef2561.1 ms0 ms6 / 6 ms0 / 0 ms0 / 0 ms34,252.2 ms0 ms2,924 / 20 ms0 / 0 ms0 / 0 ms
W10-ef5122.3 ms0 ms5 / 5 ms0 / 0 ms0 / 0 ms51,040.1 ms0 ms4,664 / 25 ms0 / 0 ms0 / 0 ms
W12-upload18.6 ms0 ms5 / 3 ms8 / 8 ms0 / 0 ms4,943.4 ms0 ms459 / 7 ms48 / 43 ms0 / 0 ms
W12-sel13.6 ms0 ms4 / 4 ms0 / 0 ms0 / 0 ms65,654.2 ms0 ms2,454 / 3 ms0 / 0 ms0 / 0 ms
W12-sel1012.3 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms99,290.4 ms0 ms5,976 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef321.3 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms12,271.2 ms0 ms1,326 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef641.1 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms12,168.3 ms0 ms1,285 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef1281.2 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms12,120.3 ms0 ms1,288 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef2561.1 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms12,139.7 ms0 ms1,289 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef5120.9 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms12,046.5 ms0 ms1,293 / 2 ms0 / 0 ms0 / 0 ms
W12-sel10-ef321.0 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms26,205.4 ms0 ms3,230 / 1 ms0 / 0 ms0 / 0 ms
W12-sel10-ef642.1 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms27,344.5 ms0 ms3,387 / 1 ms0 / 0 ms0 / 0 ms
W12-sel10-ef1282.4 ms0 ms1 / 1 ms0 / 0 ms0 / 0 ms29,547.8 ms0 ms3,644 / 1 ms0 / 0 ms0 / 0 ms
W12-sel10-ef2562.6 ms0 ms1 / 1 ms0 / 0 ms0 / 0 ms32,082.7 ms0 ms3,968 / 1 ms0 / 0 ms0 / 0 ms
W12-sel10-ef5122.8 ms0 ms1 / 1 ms0 / 0 ms0 / 0 ms36,426.6 ms0 ms4,519 / 1 ms0 / 0 ms0 / 0 ms
W132.2 ms0 ms22 / 22 ms0 / 0 ms0 / 0 ms2,194.2 ms0 ms297 / 50 ms0 / 0 ms0 / 0 ms
W11-steady12,368.5 ms0 ms2,159 / 93 ms5 / 4 ms0 / 0 ms152,429.9 ms0 ms13,687 / 67 ms197 / 56 ms0 / 0 ms
W1171,348.8 ms0 ms12,306 / 205 ms0 / 0 ms0 / 0 ms437,856.7 ms0 ms36,582 / 81 ms251 / 64 ms0 / 0 ms

A dash under blocked on disk is not a zero: most hosts ship with kernel.task_delayacct=0, which reports the field as a permanent zero and would manufacture the strongest claim here — that the memory-resident engine never waits for a device — out of a sysctl. bench/setup.py apply turns it on.

Hardware counters cycles, DRAM loads, TLB walks, IPC per query

What the core did per query, from perf stat attached to the engine for the same window as the /proc counters. §5's cost model is a set of claims about instructions per cycle, DRAM traffic and TLB reach; these are those quantities, measured on the row the headline quotes rather than on a microbenchmark.

What one query cost, in cycles

Lower is better; the bar between a pair is the gap. Load rows are absent: they have no queries to divide by, and an absolute count under a per-query axis would be a different quantity wearing this one's label.

Demand loads from DRAM per query

Demand loads served from DRAM, times the cache line this host reports. Lower is better. Demand only: the hardware prefetcher's fills are a separate counter and are not in this number, so a row that streams — an exact scan above all — moved far more than this says. On the graph rows, where there is little for a prefetcher to predict, it is most of the traffic and is the outstanding-miss quantity §5.2 argues the engine is limited by.

TLB walks per query

Data TLB misses that reached a page walk, per query. Lower is better. §5.5 argues a memory-resident index needs hugepage care; this is what not taking it costs, and `--no-huge-pages` is the A/B arm that prices it.

Instructions per cycle

How well the core was fed while it ran. Not a score: a low IPC on a memory-bound row is what §5.2 predicts, and a high one on a row that does more work per query is not a win. Read it beside the two charts above.

Branch mispredictions per 1k instructions

A graph traversal is a chain of data-dependent branches and none of them is predictable from the last query, so this is the column that separates a slow kernel from an unpredictable walk. Per thousand instructions rather than per branch: `branches` costs a PMU counter that `ref-cycles` needs more, and MPKI is the comparable form anyway.

workloadstrawmANNQdrant
IPCGHzbranch MPKIcycles/querydemand DRAM/queryTLB walks/queryIPCGHzbranch MPKIcycles/querydemand DRAM/queryTLB walks/query
W0-upload1.522.011.005x nominal5.36---1.352.011.004x nominal4.58---
W01.392.011.006x nominal5.59268,7697.1 KiB1,206.51.142.011.006x nominal3.31494,35845.9 KiB1,429.6
W11.822.011.007x nominal0.75---1.442.011.005x nominal3.76---
W21.282.011.005x nominal4.52---1.082.011.005x nominal4.01---
W31.172.011.005x nominal5.21726,75652.1 KiB3,355.71.172.011.007x nominal3.20906,3491,003.6 KiB3,692.5
W41.562.011.007x nominal4.48535,49764.2 KiB2,871.90.912.011.006x nominal3.761,037,4021,095.7 KiB3,052.6
W4-sat501.452.011.006x nominal4.90578,30449.3 KiB3,172.80.972.011.006x nominal3.821,082,5051,089.6 KiB3,512.2
W4-sat701.462.011.006x nominal4.96569,98449.5 KiB3,033.20.962.011.006x nominal3.791,082,8371,090.7 KiB3,370.8
W4-sat901.482.011.007x nominal4.90562,19549.7 KiB2,995.70.972.011.006x nominal3.731,006,7401,066.2 KiB3,217.0
W51.572.011.007x nominal4.67500,01367.6 KiB2,883.30.902.011.006x nominal3.88899,6671,041.2 KiB2,899.5
W6-upload1.392.011.006x nominal4.37---1.792.011.006x nominal4.61---
W61.822.011.006x nominal4.87451,55666.4 KiB3,844.51.542.011.006x nominal3.41762,826222.6 KiB2,743.2
W6-ef321.882.011.006x nominal3.46151,41221.8 KiB1,315.21.602.011.006x nominal2.44346,55973.7 KiB1,070.4
W6-ef641.832.011.007x nominal4.23254,61737.5 KiB2,091.81.612.011.006x nominal2.87473,993123.9 KiB1,667.1
W6-ef1281.822.011.007x nominal4.86451,94166.3 KiB3,846.11.582.011.005x nominal3.35734,503210.6 KiB2,672.9
W6-ef2561.802.011.007x nominal5.50830,087122.9 KiB7,390.91.532.011.006x nominal3.821,253,620371.1 KiB4,548.3
W6-ef5121.772.011.007x nominal6.061,574,080233.8 KiB14,672.11.502.011.005x nominal4.092,201,488670.8 KiB7,775.7
W7-upload1.282.011.006x nominal4.54---2.112.011.006x nominal3.92---
W71.712.011.007x nominal6.06548,92256.8 KiB3,172.51.642.011.006x nominal3.50751,071198.9 KiB1,574.2
W7-2bit-upload1.282.011.007x nominal4.57---2.252.011.006x nominal3.61---
W7-2bit1.632.011.006x nominal6.56478,79958.6 KiB2,644.81.672.011.006x nominal3.31825,827229.1 KiB2,676.8
W7-1p5bit-upload1.282.011.005x nominal4.57---2.292.011.005x nominal3.58---
W7-1p5bit1.652.011.006x nominal6.44491,73258.8 KiB2,750.91.682.011.006x nominal3.28845,435234.1 KiB2,768.4
W8-upload2.312.011.007x nominal2.23---4.432.011.006x nominal0.94---
W82.732.011.007x nominal2.90551,21559.6 KiB1,875.52.272.011.006x nominal1.98772,849182.8 KiB1,906.1
W14-1bit-upload1.332.011.005x nominal4.34---2.202.011.005x nominal2.81---
W14-1bit1.812.011.006x nominal4.66544,64065.3 KiB3,064.51.492.011.006x nominal2.98904,764258.9 KiB2,032.2
W14-1p5bit-upload1.342.011.006x nominal4.25---2.312.011.005x nominal2.60---
W14-1p5bit1.732.011.005x nominal4.40595,09581.2 KiB3,462.01.492.011.006x nominal3.06930,872267.0 KiB2,299.3
W14-2bit-upload1.322.011.005x nominal4.34---2.292.011.005x nominal2.70---
W14-2bit1.512.011.006x nominal4.87593,842119.0 KiB3,646.81.472.011.006x nominal3.32865,527248.6 KiB2,314.0
W14-4bit-upload1.332.011.005x nominal4.30---2.192.011.005x nominal3.28---
W14-4bit1.762.011.005x nominal5.02476,05766.3 KiB3,985.91.642.011.006x nominal3.22778,110212.5 KiB2,560.9
W92.062.011.007x nominal0.0172,884,33026,601.8 KiB83,053.51.322.011.006x nominal0.15126,763,98310,965.1 KiB126,516.4
W10-ef321.672.011.007x nominal3.22185,00534.5 KiB996.91.142.011.006x nominal2.65458,480362.6 KiB1,261.9
W10-ef641.642.011.006x nominal3.88300,66746.5 KiB1,690.81.042.011.007x nominal3.19683,247624.3 KiB2,061.2
W10-ef1281.602.011.007x nominal4.45526,23964.4 KiB3,014.50.972.011.006x nominal3.761,063,9281,095.1 KiB3,351.2
W10-ef2561.542.011.007x nominal4.94974,14798.1 KiB5,664.80.942.011.006x nominal4.271,740,5301,898.8 KiB5,487.5
W10-ef5121.462.011.006x nominal5.371,885,513159.3 KiB11,152.70.892.011.006x nominal4.723,067,8103,409.8 KiB9,107.6
W12-upload1.402.011.007x nominal4.98---1.352.011.006x nominal3.98---
W12-sel11.202.011.006x nominal4.48418,177719.8 KiB1,075.51.322.011.006x nominal0.80751,522725.0 KiB2,498.8
W12-sel101.242.011.006x nominal1.002,876,9335,819.1 KiB4,717.02.162.011.006x nominal1.057,283,9206,325.5 KiB18,027.2
W12-sel1-ef321.202.011.007x nominal4.47418,813720.6 KiB1,071.41.352.011.007x nominal0.69715,256705.3 KiB2,390.0
W12-sel1-ef641.212.011.007x nominal4.47416,662720.4 KiB1,071.91.362.011.007x nominal0.67708,012708.6 KiB2,382.1
W12-sel1-ef1281.202.011.007x nominal4.49416,086720.6 KiB1,073.71.362.011.007x nominal0.68709,083707.9 KiB2,386.8
W12-sel1-ef2561.202.011.007x nominal4.48415,953720.0 KiB1,071.21.362.011.007x nominal0.68709,585707.4 KiB2,387.7
W12-sel1-ef5121.202.011.007x nominal4.49415,264720.1 KiB1,072.11.362.011.007x nominal0.67710,528708.4 KiB2,381.2
W12-sel10-ef321.682.011.007x nominal2.98974,133356.7 KiB1,938.22.292.011.007x nominal0.706,147,9025,750.6 KiB17,371.5
W12-sel10-ef641.552.011.006x nominal3.561,679,077609.9 KiB3,440.72.242.011.007x nominal0.836,577,7795,992.5 KiB17,608.0
W12-sel10-ef1281.242.011.007x nominal1.002,877,3795,744.3 KiB4,715.72.152.011.006x nominal1.057,306,7666,335.7 KiB17,991.2
W12-sel10-ef2561.242.011.007x nominal1.002,875,0905,732.2 KiB4,718.02.082.011.006x nominal1.388,346,1436,722.9 KiB18,452.6
W12-sel10-ef5121.232.011.006x nominal1.002,891,9575,828.0 KiB4,716.31.992.011.006x nominal1.839,933,8567,192.7 KiB19,093.4
W131.372.011.007x nominal1.2540,0950.9 KiB10.91.462.011.007x nominal1.43136,3031.3 KiB30.7
W11-steady1.642.011.005x nominal4.20585,62494.3 KiB3,045.31.702.011.005x nominal2.013,128,5951,857.1 KiB4,742.6
W111.642.011.006x nominal3.82694,807220.7 KiB3,425.11.732.011.006x nominal1.507,046,5384,315.9 KiB11,945.5

Nothing here is scaled. Where perf had to multiplex the group, the values it prints are extrapolations from the fraction of the row each counter was on, and they are withheld rather than shown — the same rule the scheduler table applies to a thread that exited. An event this host does not implement is likewise blank, never zero.

The two instruments disagree on these rows. Qdrant: perf and /proc disagree on minor faults by up to 11% on W1, W2, W6-upload, W7-upload, W7-2bit-upload, W7-1p5bit-upload, W8-upload, W14-1bit-upload, W14-1p5bit-upload, W14-2bit-upload, W14-4bit-upload, W12-upload, W11-steady, W11; Qdrant: perf and /proc disagree on context switches by up to 23% on W8-upload, W14-1bit-upload, W14-1p5bit-upload, W14-2bit-upload, W14-4bit-upload. perf keeps an exiting thread's counts and the /proc sums do not, so a gap here is usually the same lost-thread effect the scheduler table reports as coverage.

Collection config what each engine says it built

Read back from the engine rather than taken from the request. --segments 1 sets Qdrant's default_segment_number, which its optimizer treats as a target, and the segment count is the largest confound in the ef comparison. strawmANN held 1 segment; Qdrant held 2 segments.

Where the engines disagree a cell reads strawmANN / Qdrant, and is marked.

collectionsegmentspopulated segmentsrequested segmentspointsindexed vectorsvector sizehnsw mhnsw ef_constructquantizationshardsvector residency
bench01 / 2- / 1- / 11,000,0001,000,000416100-1cached
bench11 / 5- / 5- / 11,000,0000 / 185,40012816100-1cached
bench21 / 2- / 1- / 11,000,0001,000,00012816100-1cached
bench61 / 2- / 1- / 11,000,0001,000,00012816100scalar1cached
bench71 / 2- / 1- / 11,000,0001,000,00012816100binary1cached
bench7b21 / 2- / 1- / 11,000,0001,000,00012816100binary1cached
bench7b151 / 2- / 1- / 11,000,0001,000,00012816100binary1cached
bench81 / 2- / 1- / 11,000,0001,000,00012816100product1cached
bench14t11 / 2- / 1- / 11,000,0001,000,00012816100turboquant1cached
bench14t151 / 2- / 1- / 11,000,0001,000,00012816100turboquant1cached
bench14t21 / 2- / 1- / 11,000,0001,000,00012816100turboquant1cached
bench14t41 / 2- / 1- / 11,000,0001,000,00012816100turboquant1cached
bench121 / 2- / 1- / 1200,000200,00012816100-1cached

After the mutating rows bench2 held strawmANN 1,250,000 (+250,000), 1,250,000 of them indexed; Qdrant 1,250,000 (+250,000), 1,246,100 of them indexed. The table above is the state the throughput, latency and recall rows searched; this is what W11 left, and is that row's subject rather than theirs.

bench1 was read back straight after its row and dropped, with no settle between, so an engine still building it reports a snapshot taken mid-ingest. Its cells are not marked as a disagreement.

Per workload every metric of every row, engine beside engine

Metric down, engine across, so a comparison is two adjacent cells. Metrics a row did not measure are dropped rather than shown empty.

W0-upload transport floor: load

upload · collection=bench0 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock22.4 s31.4 s1.41x
of which upload1.2 s7.3 s5.97x
of which index wait19.1 s22.1 s1.16x
time to Green19.1 s22.1 s1.16x
cpu126.7 s160.3 s1.27x
cpu, % of wall567%510%
waiting for a core59.6 ms13,962.1 ms234.40x
migrations613,3952,232.50x
faults min/maj114,484 / 0417,441 / 196,555
peak RSS444.3 MiB1.4 GiB3.18x
disk written61.1 MiB401.2 MiB
disk read4.0 KiB129.5 MiB

W0 d=4 floor: graph traversal with the distance taken out 1.35x

closed-loop · collection=bench0 · client -p 1 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second4,5183,3361.35x
client p50219 µs297 µs1.36x
client p99251 µs359 µs1.43x
client p99.9295 µs407 µs1.38x
server p50132 µs197 µs1.49x
server p99145 µs238 µs1.64x
wall clock11.1 s15.0 s1.35x
queries sent50,00050,000
cpu8.0 s15.5 s1.95x
cpu, % of wall72%103%
waiting for a core2.4 ms3.4 ms1.43x
migrations0195
faults min/maj0 / 0509 / 0
peak RSS444.3 MiB1.4 GiB3.18x
disk written00
disk read00
1.35x is 1.84x less work per query x 0.68x cores busy during the row (0.69 against 1.01) x 1.00x clock x 1.08x counted on-CPU share: the middle term is occupancy, not search speed d=4 floor: this measures graph traversal and heaps with the distance taken out, not request plumbing (findings 28: 76% of the server's CPU was HNSW search, 24% kernel; the RPC path is a small remainder)

W1 ingest throughput

upload · collection=bench1 · client -p 8 -t 8 -c 1 (-c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock3.2 s14.1 s4.38x
of which upload1.1 s12.0 s10.88x
cpu2.2 s77.4 s35.35x
cpu, % of wall68%550%
waiting for a core2.1 ms27,567.8 ms13,225.17x
migrations014,995
faults min/maj160,271 / 0207,287 / 261,474
peak RSS1.1 GiB2.4 GiB2.15x
disk written488.4 MiB1.6 GiB
disk read013.2 MiB

W2 index build time

upload · collection=bench2 · client -p 8 -t 8 -c 1 (-c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.3 s72.3 s1.63x
of which upload1.1 s12.7 s11.53x
of which index wait41.1 s58.1 s1.41x
time to Green41.1 s58.1 s1.41x
cpu305.5 s440.3 s1.44x
cpu, % of wall689%609%
waiting for a core136.4 ms33,352.1 ms244.60x
migrations515,6583,131.60x
faults min/maj228,003 / 0485,870 / 288,657
peak RSS1.4 GiB3.8 GiB2.77x
disk written488.4 MiB2.3 GiB
disk read0168.1 MiB

W3 search, fp32, single query 1.06x

ef=128 · closed-loop · collection=bench2 · client -p 1 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second2,1422,0131.06x
recall@100.98720.9879~equal
client p50473 µs500 µs1.06x
client p99547 µs607 µs1.11x
client p99.9607 µs762 µs1.26x
server p50381 µs409 µs1.07x
server p99446 µs501 µs1.13x
wall clock23.4 s24.9 s1.06x
queries sent50,00050,000
cpu19.9 s25.7 s1.30x
cpu, % of wall85%103%
waiting for a core2.2 ms3.4 ms1.50x
migrations0209
faults min/maj4 / 0509 / 0
peak RSS1.4 GiB3.8 GiB2.77x
disk written00
disk read00

W4 search, saturating (closed loop)

ef=128 · closed-loop · collection=bench2 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second27,94714,226-
recall@100.98720.9879
client p502.28 ms4.02 ms
client p992.53 ms12.31 ms
client p99.920.33 ms22.15 ms
server p502.20 ms2.82 ms
server p992.43 ms9.66 ms
wall clock1.8 s3.6 s
queries sent50,00050,000
cpu13.6 s27.4 s
cpu, % of wall743%773%
waiting for a core0.9 ms77,428.7 ms
migrations016,398
faults min/maj70 / 02,030 / 0
peak RSS1.4 GiB3.8 GiB
disk written00
disk read00
strawmANN pass 1 -14% against two passes that agree: one pass set the spread on this row, so a band built from it is not a noise band

W4-sat50 search, fixed rate at 50% of saturation (open loop) offered

ef=128 · open-loop · offered=7,109/s (50% of saturation, pinned reference 14,218 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second7,1097,109offered
recall@100.98720.9879~equal
client p50401 µs738 µs1.84x
client p99705 µs1.79 ms2.54x
client p99.9874 µs2.20 ms2.52x
server p50295 µs579 µs1.96x
server p99557 µs1.53 ms2.75x
wall clock28.3 s28.3 s~equal
queries sent200,000200,000
cpu60.5 s119.3 s1.97x
cpu, % of wall214%422%
waiting for a core2.9 ms125,171.7 ms43,268.19x
migrations0371,235
faults min/maj12 / 0269 / 0
peak RSS1.4 GiB3.8 GiB2.77x
disk written00
disk read00

W4-sat70 search, fixed rate at 70% of saturation (open loop) offered

ef=128 · open-loop · offered=9,953/s (70% of saturation, pinned reference 14,218 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second9,9529,952offered
recall@100.98720.9879~equal
client p50496 µs822 µs1.66x
client p99947 µs1.98 ms2.09x
client p99.91.10 ms2.87 ms2.60x
server p50369 µs636 µs1.73x
server p99774 µs1.70 ms2.20x
wall clock20.2 s20.2 s~equal
queries sent200,000200,000
cpu58.3 s120.3 s2.06x
cpu, % of wall288%595%
waiting for a core13.7 ms168,810.7 ms12,343.01x
migrations0370,251
faults min/maj34 / 0333 / 0
peak RSS1.4 GiB3.8 GiB2.77x
disk written00
disk read00

W4-sat90 search, fixed rate at 90% of saturation (open loop) offered

ef=128 · open-loop · offered=12,796/s (90% of saturation, pinned reference 14,218 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second12,79512,795offered
recall@100.98720.9879~equal
client p50563 µs1.18 ms2.10x
client p991.11 ms4.49 ms4.03x
client p99.91.23 ms8.34 ms6.80x
server p50448 µs859 µs1.92x
server p99919 µs3.14 ms3.42x
wall clock15.8 s15.8 s~equal
queries sent200,000200,000
cpu57.9 s106.6 s1.84x
cpu, % of wall367%677%
waiting for a core1.1 ms109,704.2 ms96,130.60x
migrations0148,783
faults min/maj20 / 01,118 / 0
peak RSS1.4 GiB3.8 GiB2.77x
disk written00
disk read00

W5 search batched (16 distinct dataset queries per request) 1.64x

ef=128 · closed-loop · collection=bench2 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second28,15617,2171.64x
recall@100.98720.9879~equal
client p5036.08 ms57.74 ms1.60x
client p9937.03 ms98.66 ms2.66x
client p99.953.77 ms116.90 ms2.17x
server p5035.94 ms52.63 ms1.46x
server p9936.63 ms88.09 ms2.40x
wall clock3.6 s2.9 s0.82x
queries sent100,00050,000
cpu25.0 s22.7 s0.91x
cpu, % of wall701%777%
waiting for a core1.0 ms71,874.4 ms72,373.16x
migrations01,786
faults min/maj147 / 038,695 / 0
peak RSS1.4 GiB3.8 GiB2.77x
disk written00
disk read00
strawmANN: per-batch latency (16 queries/request); queries: dataset, random-sample; -n 100000 (2x the table's 50000) Qdrant: per-batch latency (16 queries/request); queries: dataset, random-sample batched 16, so qps and rps differ by 16x; the ratio uses qps

W6-upload scalar quantization: load

upload · collection=bench6 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock43.8 s59.1 s1.35x
of which upload1.5 s10.9 s7.16x
of which index wait40.1 s47.1 s1.17x
time to Green40.1 s47.1 s1.17x
cpu299.7 s328.6 s1.10x
cpu, % of wall685%556%
waiting for a core111.0 ms22,398.0 ms201.87x
migrations015,672
faults min/maj277,753 / 0561,106 / 304,998
peak RSS2.4 GiB4.5 GiB1.86x
disk written488.4 MiB2.7 GiB
disk read4.0 KiB167.1 MiB

W6 quantized: scalar 1.77x

ef=128 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second33,45518,9031.77x
recall@100.98880.9876~equal
client p501.91 ms2.96 ms1.55x
client p992.07 ms9.33 ms4.52x
client p99.92.76 ms23.34 ms8.47x
server p501.83 ms1.71 ms0.93x
server p991.97 ms6.87 ms3.48x
wall clock3.1 s2.7 s0.88x
queries sent100,00050,000
cpu22.8 s20.4 s0.89x
cpu, % of wall747%762%
waiting for a core2.2 ms68,753.5 ms31,287.51x
migrations015,398
faults min/maj10 / 01,773 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W6-ef32 SQ8 recall control, ef=32 (latency only) 1.99x

ef=32 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=200,000 · oversampling=3.2 · rescore=true
metricstrawmANNQdrant
queries/second77,34538,7801.99x
recall@100.90920.8996~equal
client p50533 µs1.48 ms2.79x
client p991.41 ms3.93 ms2.79x
client p99.91.98 ms5.61 ms2.84x
server p5078 µs622 µs8.01x
server p99268 µs2.33 ms8.70x
wall clock2.7 s2.6 s0.98x
queries sent200,000100,000
cpu15.6 s19.7 s1.26x
cpu, % of wall576%745%
waiting for a core2.0 ms47,775.6 ms23,816.81x
migrations023,599
faults min/maj90 / 0470 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00
strawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000) strawmANN: 0.46 ms of the client's 0.53 ms p50 is not server time (7x), so 85% of this row is the load generator and the socket

W6-ef64 SQ8 recall control, ef=64 (latency only) 2.02x

ef=64 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=200,000 · oversampling=6.4 · rescore=true
metricstrawmANNQdrant
queries/second60,90630,0912.02x
recall@100.96400.9603~equal
client p501.00 ms1.91 ms1.91x
client p991.51 ms5.36 ms3.55x
client p99.92.13 ms8.46 ms3.98x
server p50789 µs1.14 ms1.44x
server p99995 µs3.69 ms3.71x
wall clock3.4 s3.4 s~equal
queries sent200,000100,000
cpu25.5 s25.6 s~equal
cpu, % of wall747%756%
waiting for a core1.4 ms56,843.6 ms42,062.14x
migrations018,043
faults min/maj44 / 0122 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00
strawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000)

W6-ef128 SQ8 recall control, ef=128 (latency only) 1.67x

ef=128 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second33,45920,0241.67x
recall@100.98880.9876~equal
client p501.91 ms2.98 ms1.56x
client p992.07 ms6.50 ms3.15x
client p99.92.88 ms22.86 ms7.94x
server p501.83 ms2.53 ms1.38x
server p991.97 ms5.39 ms2.73x
wall clock3.1 s2.5 s0.83x
queries sent100,00050,000
cpu22.8 s18.7 s0.82x
cpu, % of wall747%739%
waiting for a core1.0 ms10,640.3 ms11,180.03x
migrations06,029
faults min/maj0 / 0111 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W6-ef256 SQ8 recall control, ef=256 (latency only) 1.45x

ef=256 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=25.6 · rescore=true
metricstrawmANNQdrant
queries/second17,62212,1611.45x
recall@100.99740.9968~equal
client p503.64 ms5.07 ms1.40x
client p993.94 ms9.26 ms2.35x
client p99.920.52 ms21.82 ms1.06x
server p503.56 ms4.72 ms1.33x
server p993.85 ms8.17 ms2.12x
wall clock2.9 s4.2 s1.45x
queries sent50,00050,000
cpu21.0 s31.8 s1.52x
cpu, % of wall729%765%
waiting for a core0.9 ms13,088.6 ms13,981.18x
migrations06,239
faults min/maj0 / 0523 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00

W6-ef512 SQ8 recall control, ef=512 (latency only) 1.28x

ef=512 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=51.2 · rescore=true
metricstrawmANNQdrant
queries/second9,1517,1641.28x
recall@100.99950.9993~equal
client p507.04 ms8.92 ms1.27x
client p997.67 ms11.93 ms1.56x
client p99.914.93 ms21.60 ms1.45x
server p506.96 ms8.66 ms1.24x
server p997.57 ms11.25 ms1.49x
wall clock5.5 s7.0 s1.28x
queries sent50,00050,000
cpu39.6 s55.6 s1.40x
cpu, % of wall719%792%
waiting for a core1.8 ms12,144.6 ms6,780.01x
migrations01,080
faults min/maj3 / 0386 / 0
peak RSS2.4 GiB4.5 GiB1.86x
disk written00
disk read00

W7-upload binary quantization: load

upload · collection=bench7 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.8 s61.9 s1.38x
of which upload1.5 s10.7 s6.97x
of which index wait41.1 s49.1 s1.19x
time to Green41.1 s49.1 s1.19x
cpu305.1 s349.8 s1.15x
cpu, % of wall681%565%
waiting for a core114.5 ms19,990.3 ms174.55x
migrations118,49618,496.00x
faults min/maj247,541 / 0556,124 / 319,189
peak RSS3.4 GiB5.1 GiB1.50x
disk written488.4 MiB2.6 GiB
disk read12.0 KiB189.4 MiB

W7 quantized: binary + oversampling

ef=128 · closed-loop · collection=bench7 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second27,30619,742-
recall@100.06500.0658
client p502.33 ms3.09 ms
client p992.52 ms6.53 ms
client p99.92.67 ms18.21 ms
server p502.25 ms2.67 ms
server p992.44 ms5.57 ms
wall clock3.7 s2.6 s
queries sent100,00050,000
cpu27.8 s19.2 s
cpu, % of wall743%745%
waiting for a core2.3 ms10,017.6 ms
migrations04,916
faults min/maj0 / 01,773 / 0
peak RSS3.4 GiB5.1 GiB
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000) recall below the usable floor: 0.0650 and 0.0658, both under 0.50 — this row characterises the encoding, not the engines

W7-2bit-upload binary quantization, 2 bits: load

upload · collection=bench7b2 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock46.8 s60.8 s1.30x
of which upload1.6 s11.6 s7.48x
of which index wait43.1 s47.1 s1.09x
time to Green43.1 s47.1 s1.09x
cpu306.0 s320.2 s1.05x
cpu, % of wall654%526%
waiting for a core114.5 ms20,986.5 ms183.29x
migrations117,32017,320.00x
faults min/maj247,485 / 0507,387 / 312,803
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.5 GiB
disk read0189.0 MiB

W7-2bit quantized: binary quantization, 2 bits + oversampling

ef=128 · closed-loop · collection=bench7b2 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second31,40517,623-
recall@100.54520.5026
client p502.03 ms3.11 ms
client p992.16 ms10.83 ms
client p99.92.54 ms22.41 ms
server p501.95 ms1.89 ms
server p992.07 ms8.15 ms
wall clock3.3 s2.9 s
queries sent100,00050,000
cpu24.2 s21.9 s
cpu, % of wall743%762%
waiting for a core2.0 ms74,642.5 ms
migrations015,579
faults min/maj0 / 02,152 / 0
peak RSS4.7 GiB5.2 GiB
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000) recall unequal: 0.5452 vs 0.5026; §7.4 compares at equal recall; the rescore pools match, so the encoders differ

W7-1p5bit-upload binary quantization, 1.5 bits: load

upload · collection=bench7b15 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock46.8 s67.1 s1.43x
of which upload1.5 s11.9 s7.78x
of which index wait43.1 s52.1 s1.21x
time to Green43.1 s52.1 s1.21x
cpu306.0 s380.6 s1.24x
cpu, % of wall654%567%
waiting for a core122.2 ms21,732.9 ms177.89x
migrations218,1679,083.50x
faults min/maj247,481 / 0562,838 / 321,988
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.7 GiB
disk read0208.8 MiB

W7-1p5bit quantized: binary quantization, 1.5 bits + oversampling

ef=128 · closed-loop · collection=bench7b15 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second30,52317,280-
recall@100.38170.3428
client p502.08 ms3.16 ms
client p992.23 ms10.86 ms
client p99.92.56 ms23.06 ms
server p502.00 ms1.93 ms
server p992.14 ms8.33 ms
wall clock3.3 s2.9 s
queries sent100,00050,000
cpu24.9 s22.4 s
cpu, % of wall745%765%
waiting for a core2.1 ms76,285.0 ms
migrations016,529
faults min/maj0 / 02,376 / 0
peak RSS4.7 GiB5.2 GiB
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000) recall below the usable floor: 0.3817 and 0.3428, both under 0.50 — this row characterises the encoding, not the engines

W8-upload PQ: load

upload · collection=bench8 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock54.9 s99.1 s1.81x
of which upload1.5 s7.8 s5.11x
of which index wait51.2 s89.2 s1.74x
time to Green51.2 s89.2 s1.74x
cpu388.8 s566.7 s1.46x
cpu, % of wall708%572%
waiting for a core139.9 ms10,648.1 ms76.11x
migrations158,58658,586.00x
faults min/maj249,660 / 0462,533 / 240,643
peak RSS4.0 GiB5.2 GiB1.32x
disk written488.4 MiB2.2 GiB
disk read12.0 KiB145.1 MiB

W8 quantized: PQ 1.41x

ef=128 · closed-loop · collection=bench8 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second27,15319,2401.41x
recall@100.98290.9780~equal
client p502.36 ms3.19 ms1.35x
client p992.54 ms6.68 ms2.63x
client p99.92.77 ms23.63 ms8.54x
server p502.28 ms2.83 ms1.24x
server p992.46 ms5.89 ms2.40x
wall clock3.8 s2.6 s0.70x
queries sent100,00050,000
cpu27.9 s19.6 s0.71x
cpu, % of wall743%745%
waiting for a core1.5 ms9,938.6 ms6,701.99x
migrations05,041
faults min/maj0 / 01,508 / 0
peak RSS4.0 GiB5.2 GiB1.32x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W14-1bit-upload TurboQuant, 1 bit: load

upload · collection=bench14t1 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.8 s68.1 s1.52x
of which upload1.5 s12.5 s8.22x
of which index wait41.1 s53.1 s1.29x
time to Green41.1 s53.1 s1.29x
cpu307.4 s377.5 s1.23x
cpu, % of wall687%554%
waiting for a core116.1 ms22,320.0 ms192.22x
migrations115,96915,969.00x
faults min/maj237,464 / 0518,202 / 312,766
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.5 GiB
disk read0186.0 MiB

W14-1bit quantized: TurboQuant, 1 bit + oversampling

ef=128 · closed-loop · collection=bench14t1 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second27,33116,257-
recall@100.76280.7158
client p502.34 ms3.34 ms
client p992.53 ms11.85 ms
client p99.93.03 ms19.70 ms
server p502.26 ms2.16 ms
server p992.44 ms9.40 ms
wall clock3.7 s3.1 s
queries sent100,00050,000
cpu27.6 s23.8 s
cpu, % of wall740%766%
waiting for a core1.4 ms81,501.1 ms
migrations016,389
faults min/maj0 / 02,706 / 0
peak RSS4.7 GiB5.2 GiB
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000) recall unequal: 0.7628 vs 0.7158; §7.4 compares at equal recall; the rescore pools match, so the encoders differ

W14-1p5bit-upload TurboQuant, 1.5 bits: load

upload · collection=bench14t15 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.8 s81.3 s1.81x
of which upload1.6 s13.8 s8.87x
of which index wait41.1 s65.2 s1.58x
time to Green41.1 s65.2 s1.58x
cpu309.3 s459.4 s1.49x
cpu, % of wall690%565%
waiting for a core117.4 ms27,703.1 ms235.89x
migrations117,03717,037.00x
faults min/maj240,046 / 0582,138 / 324,362
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.7 GiB
disk read0211.3 MiB

W14-1p5bit quantized: TurboQuant, 1.5 bits + oversampling

ef=128 · closed-loop · collection=bench14t15 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second24,87315,866-
recall@100.85260.8147
client p502.57 ms3.44 ms
client p992.78 ms11.97 ms
client p99.918.12 ms23.89 ms
server p502.49 ms2.25 ms
server p992.69 ms9.42 ms
wall clock2.0 s3.2 s
queries sent50,00050,000
cpu15.1 s24.5 s
cpu, % of wall736%768%
waiting for a core1.0 ms84,236.3 ms
migrations015,911
faults min/maj0 / 03,270 / 0
peak RSS4.7 GiB5.2 GiB
disk written00
disk read00
recall unequal: 0.8526 vs 0.8147; §7.4 compares at equal recall; the rescore pools match, so the encoders differ

W14-2bit-upload TurboQuant, 2 bits: load

upload · collection=bench14t2 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.9 s78.9 s1.76x
of which upload1.6 s13.7 s8.77x
of which index wait41.1 s63.1 s1.53x
time to Green41.1 s63.1 s1.53x
cpu308.6 s433.2 s1.40x
cpu, % of wall688%549%
waiting for a core120.5 ms26,059.5 ms216.32x
migrations018,325
faults min/maj242,873 / 0630,285 / 326,617
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.8 GiB
disk read0218.9 MiB

W14-2bit quantized: TurboQuant, 2 bits + oversampling

ef=128 · closed-loop · collection=bench14t2 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second24,91916,951-
recall@100.97110.9427
client p502.57 ms3.21 ms
client p992.82 ms11.03 ms
client p99.916.94 ms24.24 ms
server p502.49 ms2.03 ms
server p992.73 ms8.68 ms
wall clock2.0 s3.0 s
queries sent50,00050,000
cpu15.1 s22.8 s
cpu, % of wall735%765%
waiting for a core0.8 ms78,044.7 ms
migrations016,494
faults min/maj0 / 03,445 / 0
peak RSS4.7 GiB5.2 GiB
disk written00
disk read00
recall unequal: 0.9711 vs 0.9427; §7.4 compares at equal recall; the rescore pools match, so the encoders differ

W14-4bit-upload TurboQuant, 4 bits: load

upload · collection=bench14t4 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=1,000,000
metricstrawmANNQdrant
wall clock44.8 s74.3 s1.66x
of which upload1.6 s13.9 s8.86x
of which index wait41.1 s58.1 s1.41x
time to Green41.1 s58.1 s1.41x
cpu309.1 s382.7 s1.24x
cpu, % of wall690%515%
waiting for a core118.6 ms21,608.1 ms182.25x
migrations218,7969,398.00x
faults min/maj253,711 / 0637,899 / 334,333
peak RSS4.7 GiB5.2 GiB1.12x
disk written488.4 MiB2.9 GiB
disk read0193.3 MiB

W14-4bit quantized: TurboQuant, 4 bits + oversampling 1.69x

ef=128 · closed-loop · collection=bench14t4 · client -p 64 -t 16 -c 2 · n=100,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second31,60718,6671.69x
recall@100.98920.9847~equal
client p502.03 ms3.01 ms1.48x
client p992.19 ms9.44 ms4.31x
client p99.92.65 ms14.22 ms5.37x
server p501.94 ms1.75 ms0.90x
server p992.10 ms6.97 ms3.31x
wall clock3.2 s2.7 s0.84x
queries sent100,00050,000
cpu24.1 s20.8 s0.86x
cpu, % of wall746%764%
waiting for a core1.2 ms69,510.8 ms57,191.06x
migrations017,390
faults min/maj0 / 01,912 / 0
peak RSS4.7 GiB5.2 GiB1.12x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W9 exact / brute force 1.56x

exact · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=2,000
metricstrawmANNQdrant
queries/second1911231.56x
client p5037.34 ms65.78 ms1.76x
client p9968.90 ms77.33 ms1.12x
client p99.975.30 ms83.35 ms1.11x
server p5036.81 ms64.62 ms1.76x
server p9968.38 ms76.29 ms1.12x
wall clock10.5 s16.3 s1.56x
queries sent2,0002,000
cpu72.7 s127.3 s1.75x
cpu, % of wall694%780%
waiting for a core4.6 ms9,492.0 ms2,045.04x
migrations06,902
faults min/maj0 / 0153 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00
brute force over the whole collection, no index involved

W10-ef32 recall control, ef=32 (latency only) 2.12x

ef=32 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=100,000
metricstrawmANNQdrant
queries/second47,05022,2162.12x
recall@100.90770.8979~equal
client p50163 µs333 µs2.05x
client p99221 µs652 µs2.95x
client p99.9309 µs856 µs2.77x
server p5079 µs211 µs2.66x
server p99109 µs453 µs4.15x
wall clock2.2 s2.3 s1.04x
queries sent100,00050,000
cpu9.9 s13.1 s1.32x
cpu, % of wall452%573%
waiting for a core3.2 ms5,140.2 ms1,598.43x
migrations062,129
faults min/maj0 / 01,042 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W10-ef64 recall control, ef=64 (latency only) 2.33x

ef=64 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=100,000
metricstrawmANNQdrant
queries/second36,44715,6612.33x
recall@100.96250.9605~equal
client p50215 µs471 µs2.19x
client p99271 µs957 µs3.53x
client p99.9396 µs1.24 ms3.12x
server p50137 µs337 µs2.45x
server p99176 µs774 µs4.40x
wall clock2.8 s3.2 s1.15x
queries sent100,00050,000
cpu15.8 s19.1 s1.21x
cpu, % of wall562%593%
waiting for a core1.2 ms11,902.7 ms10,190.75x
migrations0107,170
faults min/maj0 / 0836 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W10-ef128 recall control, ef=128 (latency only) 2.38x

ef=128 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second24,26910,2052.38x
recall@100.98720.9879~equal
client p50328 µs708 µs2.16x
client p99403 µs1.52 ms3.76x
client p99.9735 µs1.95 ms2.66x
server p50254 µs561 µs2.21x
server p99321 µs1.30 ms4.06x
wall clock2.1 s4.9 s2.36x
queries sent50,00050,000
cpu13.6 s29.4 s2.16x
cpu, % of wall648%595%
waiting for a core0.7 ms22,235.9 ms32,603.90x
migrations0105,602
faults min/maj0 / 0153 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00

W10-ef256 recall control, ef=256 (latency only) 2.11x

ef=256 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second14,1186,6832.11x
recall@100.99560.9967~equal
client p50569 µs1.07 ms1.89x
client p99743 µs2.30 ms3.09x
client p99.9882 µs3.01 ms3.41x
server p50494 µs913 µs1.85x
server p99667 µs2.00 ms3.00x
wall clock3.6 s7.5 s2.10x
queries sent50,00050,000
cpu24.7 s46.5 s1.88x
cpu, % of wall692%619%
waiting for a core1.1 ms34,252.2 ms30,523.24x
migrations0127,521
faults min/maj0 / 0104 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00

W10-ef512 recall control, ef=512 (latency only) 1.88x

ef=512 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second7,4343,9641.88x
recall@100.99770.9994~equal
client p501.08 ms1.85 ms1.72x
client p991.52 ms3.72 ms2.45x
client p99.91.73 ms4.75 ms2.75x
server p50995 µs1.65 ms1.66x
server p991.43 ms3.36 ms2.35x
wall clock6.8 s12.6 s1.87x
queries sent50,00050,000
cpu47.6 s80.5 s1.69x
cpu, % of wall703%636%
waiting for a core2.3 ms51,040.1 ms22,630.00x
migrations0157,882
faults min/maj0 / 0289 / 0
peak RSS4.0 GiB5.2 GiB1.31x
disk written00
disk read00

W12-upload filtered search: load 200,000 with payloads

upload · collection=bench12 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=200,000
metricstrawmANNQdrant
wall clock11.7 s18.9 s1.62x
of which upload0.6 s2.4 s4.25x
of which index wait9.0 s14.0 s1.55x
time to Green9.0 s14.0 s1.55x
cpu48.7 s82.4 s1.69x
cpu, % of wall416%436%
waiting for a core18.6 ms4,943.4 ms265.74x
migrations05,065
faults min/maj117,259 / 0163,649 / 189,401
peak RSS4.5 GiB5.2 GiB1.16x
disk written97.8 MiB585.8 MiB
disk read16.0 KiB46.3 MiB

W12-sel1 filtered search, one keyword (~1% of bench12) 1.98x

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,26918,3591.98x
recall@101.00001.0000~equal
client p501.73 ms3.21 ms1.86x
client p992.43 ms8.32 ms3.43x
client p99.93.03 ms25.38 ms8.38x
server p501.63 ms1.50 ms0.92x
server p992.27 ms5.38 ms2.37x
wall clock2.8 s2.8 s0.98x
queries sent100,00050,000
cpu21.2 s21.1 s~equal
cpu, % of wall748%763%
waiting for a core3.6 ms65,654.2 ms18,309.36x
migrations022,449
faults min/maj138 / 01,639 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000) filtered search over a keyword payload index both engines were asked to build; whether each did is read back from the engine and refused beside the row when it did not. Recall is measured under the filter, against ground truth restricted to the matching set

W12-sel10 filtered search, any of 10 keywords (~10% of bench12) 2.26x

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4,9342,1842.26x
recall@101.00000.9982~equal
client p5012.74 ms28.87 ms2.27x
client p9914.38 ms45.06 ms3.13x
client p99.926.36 ms61.57 ms2.34x
server p5012.62 ms28.26 ms2.24x
server p9914.24 ms41.74 ms2.93x
wall clock10.2 s22.9 s2.25x
queries sent50,00050,000
cpu71.8 s182.9 s2.55x
cpu, % of wall706%798%
waiting for a core12.3 ms99,290.4 ms8,051.53x
migrations02,808
faults min/maj2 / 06,252 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
filtered search over a keyword payload index both engines were asked to build; whether each did is read back from the engine and refused beside the row when it did not. Recall is measured under the filter, against ground truth restricted to the matching set

W12-sel1-ef32 filtered recall control, one keyword, ef=32 (latency only) 1.74x

ef=32 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,22620,7731.74x
recall@101.00001.0000~equal
client p501.74 ms2.88 ms1.66x
client p991.93 ms6.40 ms3.33x
client p99.93.08 ms23.43 ms7.61x
server p501.64 ms2.29 ms1.39x
server p991.81 ms5.08 ms2.80x
wall clock2.8 s2.4 s0.87x
queries sent100,00050,000
cpu21.1 s18.3 s0.87x
cpu, % of wall748%750%
waiting for a core1.3 ms12,271.2 ms9,619.18x
migrations05,383
faults min/maj4 / 0296 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W12-sel1-ef64 filtered recall control, one keyword, ef=64 (latency only) 1.74x

ef=64 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,52820,9441.74x
recall@101.00001.0000~equal
client p501.73 ms2.85 ms1.65x
client p991.90 ms6.36 ms3.35x
client p99.92.79 ms20.14 ms7.23x
server p501.63 ms2.29 ms1.40x
server p991.76 ms5.20 ms2.96x
wall clock2.8 s2.4 s0.87x
queries sent100,00050,000
cpu21.0 s18.1 s0.86x
cpu, % of wall749%748%
waiting for a core1.1 ms12,168.3 ms11,031.99x
migrations04,950
faults min/maj0 / 036 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W12-sel1-ef128 filtered recall control, one keyword, ef=128 (latency only) 1.75x

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,39120,8271.75x
recall@101.00001.0000~equal
client p501.73 ms2.87 ms1.66x
client p991.90 ms6.41 ms3.37x
client p99.93.10 ms23.64 ms7.62x
server p501.63 ms2.28 ms1.40x
server p991.76 ms5.15 ms2.93x
wall clock2.8 s2.4 s0.87x
queries sent100,00050,000
cpu21.0 s18.1 s0.86x
cpu, % of wall748%744%
waiting for a core1.2 ms12,120.3 ms9,903.84x
migrations04,911
faults min/maj0 / 0115 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W12-sel1-ef256 filtered recall control, one keyword, ef=256 (latency only) 1.74x

ef=256 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,47920,9151.74x
recall@101.00001.0000~equal
client p501.73 ms2.87 ms1.66x
client p991.90 ms6.39 ms3.37x
client p99.92.89 ms22.63 ms7.84x
server p501.63 ms2.28 ms1.40x
server p991.75 ms5.13 ms2.93x
wall clock2.8 s2.4 s0.86x
queries sent100,00050,000
cpu21.0 s18.2 s0.87x
cpu, % of wall746%748%
waiting for a core1.1 ms12,139.7 ms11,390.41x
migrations04,977
faults min/maj0 / 089 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W12-sel1-ef512 filtered recall control, one keyword, ef=512 (latency only) 1.74x

ef=512 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=100,000
metricstrawmANNQdrant
queries/second36,40520,8761.74x
recall@101.00001.0000~equal
client p501.73 ms2.87 ms1.66x
client p991.90 ms6.35 ms3.35x
client p99.93.01 ms18.56 ms6.17x
server p501.63 ms2.28 ms1.40x
server p991.75 ms5.14 ms2.94x
wall clock2.8 s2.4 s0.87x
queries sent100,00050,000
cpu21.0 s18.1 s0.86x
cpu, % of wall746%745%
waiting for a core0.9 ms12,046.5 ms13,113.31x
migrations05,059
faults min/maj0 / 023 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
strawmANN: -n 100000 (2x the table's 50000)

W12-sel10-ef32 filtered recall control, any of 10 keywords, ef=32 (latency only)

ef=32 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second14,9462,588-
recall@100.97840.9656
client p504.27 ms24.72 ms
client p994.56 ms27.92 ms
client p99.921.44 ms36.85 ms
server p504.18 ms24.18 ms
server p994.46 ms27.45 ms
wall clock3.4 s19.4 s
queries sent50,00050,000
cpu24.6 s154.2 s
cpu, % of wall727%796%
waiting for a core1.0 ms26,205.4 ms
migrations0326
faults min/maj0 / 01,613 / 0
peak RSS4.5 GiB5.2 GiB
disk written00
disk read00
recall unequal: 0.9784 vs 0.9656; §7.4 compares at equal recall

W12-sel10-ef64 filtered recall control, any of 10 keywords, ef=64 (latency only) 3.53x

ef=64 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second8,5472,4203.53x
recall@100.99530.9915~equal
client p507.50 ms26.24 ms3.50x
client p998.04 ms29.92 ms3.72x
client p99.924.43 ms37.34 ms1.53x
server p507.41 ms25.87 ms3.49x
server p997.94 ms29.43 ms3.70x
wall clock5.9 s20.7 s3.52x
queries sent50,00050,000
cpu42.3 s165.2 s3.91x
cpu, % of wall718%798%
waiting for a core2.1 ms27,344.5 ms12,755.56x
migrations0307
faults min/maj0 / 01,921 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00

W12-sel10-ef128 filtered recall control, any of 10 keywords, ef=128 (latency only) 2.26x

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4,9302,1782.26x
recall@101.00000.9982~equal
client p5012.75 ms29.01 ms2.28x
client p9914.27 ms35.07 ms2.46x
client p99.928.53 ms46.94 ms1.64x
server p5012.63 ms28.62 ms2.27x
server p9914.13 ms34.65 ms2.45x
wall clock10.2 s23.0 s2.26x
queries sent50,00050,000
cpu71.9 s183.5 s2.55x
cpu, % of wall706%798%
waiting for a core2.4 ms29,547.8 ms12,147.87x
migrations0391
faults min/maj0 / 01,575 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00

W12-sel10-ef256 filtered recall control, any of 10 keywords, ef=256 (latency only) 2.59x

ef=256 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4,9361,9082.59x
recall@101.00000.9996~equal
client p5012.74 ms32.89 ms2.58x
client p9914.25 ms42.94 ms3.01x
client p99.924.12 ms51.42 ms2.13x
server p5012.62 ms32.26 ms2.56x
server p9914.11 ms42.19 ms2.99x
wall clock10.2 s26.2 s2.58x
queries sent50,00050,000
cpu71.8 s209.6 s2.92x
cpu, % of wall706%799%
waiting for a core2.6 ms32,082.7 ms12,163.83x
migrations0490
faults min/maj0 / 02,883 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00

W12-sel10-ef512 filtered recall control, any of 10 keywords, ef=512 (latency only) 3.06x

ef=512 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4,9071,6053.06x
recall@101.00000.9999~equal
client p5012.81 ms38.82 ms3.03x
client p9914.33 ms54.30 ms3.79x
client p99.924.78 ms59.87 ms2.42x
server p5012.70 ms38.07 ms3.00x
server p9914.19 ms53.86 ms3.79x
wall clock10.2 s31.2 s3.05x
queries sent50,00050,000
cpu72.2 s249.2 s3.45x
cpu, % of wall706%799%
waiting for a core2.8 ms36,426.6 ms13,120.65x
migrations0456
faults min/maj0 / 02,994 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00

W13 scroll / pagination 1.12x

closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=200,000
metricstrawmANNQdrant
queries/second56,64150,4921.12x
client p50127 µs146 µs1.15x
client p99205 µs292 µs1.43x
client p99.9238 µs459 µs1.93x
server p5011 µs28 µs2.62x
server p9915 µs100 µs6.51x
wall clock3.6 s4.1 s1.12x
queries sent200,000200,000
cpu5.3 s18.0 s3.43x
cpu, % of wall144%442%
waiting for a core2.2 ms2,194.2 ms1,005.72x
migrations0230,194
faults min/maj0 / 0440 / 0
peak RSS4.5 GiB5.2 GiB1.16x
disk written00
disk read00
-n 200000 (4x the table's 50000) strawmANN: 0.12 ms of the client's 0.13 ms p50 is not server time (12x), so 91% of this row is the load generator and the socket Qdrant: 0.12 ms of the client's 0.15 ms p50 is not server time (5x), so 81% of this row is the load generator and the socket 1.12x is 3.40x less work per query x 0.33x cores busy during the row (1.46 against 4.48) x 1.00x clock x 1.01x counted on-CPU share: the middle term is occupancy, not search speed

W11-steady mixed read/write below the rebuild threshold: search bench2 while 50,000 synthetic points append

ef=128 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=100,000,000
metricstrawmANNQdrant
queries/second21,6244,481-
client p50329 µs1.51 ms
client p991.95 ms6.72 ms
client p99.92.93 ms13.70 ms
server p50255 µs1.18 ms
server p991.05 ms5.89 ms
wall clock32.9 s31.7 s
queries sent696,388140,836
cpu210.3 s230.0 s
cpu, % of wall639%725%
waiting for a core12,368.5 ms152,429.9 ms
migrations54243,563
faults min/maj1,162,430 / 01,194,422 / 261,045
peak RSS4.7 GiB10.3 GiB
disk written24.5 MiB4.6 GiB
disk read0519.6 MiB
strawmANN: qps over the 25.0 s of the append the search saw (22,171 over the whole search); append 2,000 points/s Qdrant: qps over the 25.0 s of the append the search saw (4,484 over the whole search); append 2,000 points/s search-during-write; no recall join

W11 mixed read/write: search bench2 while 200,000 synthetic points append (runs last)

ef=128 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=100,000,000
metricstrawmANNQdrant
queries/second17,8002,017-
client p50333 µs2.77 ms
client p992.00 ms16.97 ms
client p99.93.20 ms26.23 ms
server p50258 µs2.30 ms
server p991.16 ms15.78 ms
wall clock78.9 s76.2 s
queries sent1,448,903159,737
cpu517.5 s577.2 s
cpu, % of wall656%758%
waiting for a core71,348.8 ms437,856.7 ms
migrations224248,376
faults min/maj8,099,839 / 01,708,094 / 405,980
peak RSS4.7 GiB10.7 GiB
disk written97.9 MiB6.1 GiB
disk read0730.1 MiB
strawmANN: qps over the 60.6 s of the append the search saw (19,108 over the whole search); append 3,300 points/s Qdrant: qps over the 60.6 s of the append the search saw (2,106 over the whole search); append 3,300 points/s search-during-write; no recall join
Host discipline the §7.1 gate, per check, and ambient load per row

Ambient load per row

The §7.1 gate checks the machine once, at the start. Colour is the engine, as everywhere else; a hatched bar with a red edge is a row that had another process on the box while it ran, which the gate cannot see.

strawmANN gate pass

environment hash 373e8531fd3d1bf6
okAMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M (24 logical)
okgovernor=performance
okboost disabled
oksmt=on
declared rather than required (§7.1 asks for SMT on or off, not
for off), and hashed, so these rows never share a chart with
SMT-off ones
cpu N and cpu N+12 share a core (12 pairs);
a --server-cpus or --client-cpus set holding both cpus of a
pair measures the engine on half the cores it names
okprofile=as-deployed (isolcpus=none nohz_full=none)
the scheduler is running as it ships, so these numbers describe a
deployment rather than the engine in isolation; they may not be
compared against an `isolated` run, and the environment hash
enforces that
okthp=madvise numa_nodes=1 numa_balancing=0
okperf_event_paranoid=-1
oktask_delayacct=1, so time blocked on a device is measurable
okperf at /usr/bin/perf, so `workloads.py run --perf` can attach
okcgroup io controller reaches the engines' own scope, so block-layer read/write operations are measurable
okzig=0.16.0
busy: Xorg(6%)
okmachine is quiescent: 0.11 cores of foreign load, under the 1.00 budget
measurement profile: as-deployed

Qdrant gate pass

environment hash 373e8531fd3d1bf6
okAMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M (24 logical)
okgovernor=performance
okboost disabled
oksmt=on
declared rather than required (§7.1 asks for SMT on or off, not
for off), and hashed, so these rows never share a chart with
SMT-off ones
cpu N and cpu N+12 share a core (12 pairs);
a --server-cpus or --client-cpus set holding both cpus of a
pair measures the engine on half the cores it names
okprofile=as-deployed (isolcpus=none nohz_full=none)
the scheduler is running as it ships, so these numbers describe a
deployment rather than the engine in isolation; they may not be
compared against an `isolated` run, and the environment hash
enforces that
okthp=madvise numa_nodes=1 numa_balancing=0
okperf_event_paranoid=-1
oktask_delayacct=1, so time blocked on a device is measurable
okperf at /usr/bin/perf, so `workloads.py run --perf` can attach
okcgroup io controller reaches the engines' own scope, so block-layer read/write operations are measurable
okzig=0.16.0
busy: Xorg(5%)
okmachine is quiescent: 0.08 cores of foreign load, under the 1.00 budget
measurement profile: as-deployed
What this does not establish

No Qdrant developer has used this tool. Nothing here has been run, checked against something already known, or disagreed with by anyone outside the project: every number has one author and one reviewer, and they are the same person. A result you can refute is more useful to us than one you accept.

It has never been pointed at a real Qdrant regression. The harness detects a known ISA slowdown and correctly reports no difference on a control row. That is internal consistency, not evidence it would flag a regression in your tree or stay quiet through a refactor. bench/harness/qdrant_ab.py exists to run two of your commits through it blind, and that experiment has not been done.

Part of the measured throughput gap is kernel width, not architecture. Read from a dev checkout: Qdrant's distance path tops out at four 256-bit accumulators and has no AVX-512, while these kernels use 512-bit ones on a machine that has them. That is a real difference and it is not the same claim as "the design is faster".

The engines are not equivalent, by construction. §1 removes sharding, replication, consensus, snapshots, sparse vectors, multivectors and disk-resident operation — permanently. Payload storage and filtering were in that list until 2026-09-03 and are now built (M7), so W12 measures a filtered search with a keyword index on both engines. Anything still unbuilt answers UNIMPLEMENTED naming the construct and reports n/a, never a silent degradation. A strawman that was not faster would mean it was badly built; the question is by how much, and where the model was wrong.

Reproducing this

Everything below runs from a clone. The engine has no dependencies; the analysis path is a uv project pinned by bench/uv.lock.

scripts/doctor.py                    # what can this machine measure?
bench/setup.py check                 # §7.1 host gate: governor, boost, isolation, idle
conformance/datasets/datasets.py fetch

# one engine at a time, §7.1
zig build -Doptimize=ReleaseFast
# --connections matters: W4 opens ~32 sockets (-t 16 -c 2) and a server with
# fewer closes the excess before the HTTP/2 preface, which the client reports
# only as "transport error".
./zig-out/bin/strawmann --port 6334 --connections 64
bench/harness/workloads.py run http://localhost:6334 strawmann --sink --report

# the other half of every number: recall, and the licence to compare at all
cd conformance
cargo run --release -- relevance --engine http://localhost:6334 --label strawmann \
  --base $DATA/sift1m/sift1m.fbin --queries $DATA/sift1m/sift1m_query.fbin \
  --ground-truth $DATA/sift1m/gt/sift1m.euclid.k100.gt.json --metric euclid \
  --ef 32 64 128 256 512 --json ../bench/results/strawmann/recall.json
cargo run --release -- differ --strawmann http://localhost:6334 --qdrant http://localhost:6434 \
  --base $DATA/sift1m/sift1m.fbin --queries $DATA/sift1m/sift1m_query.fbin \
  --ground-truth $DATA/sift1m/gt/sift1m.euclid.k100.gt.json \
  --json ../bench/results/strawmann/conformance.json

uv run --project bench bench/harness/report.py strawmann qdrant

Disagreements are the point. docs/spec.md is what all of this is measured against, docs/bugs.md lists the measurement bugs found so far (each produced a plausible wrong number rather than a failure), and docs/validation.md records what has and has not been checked.