strawmANN benchmark report

strawmANN against Qdrant · AMD Ryzen AI 9 HX PRO 370 w/ Radeon 890M (24 logical) · generated 2026-10-08 08:54:50 CEST

Dataset
dbpedia-openai-1m
Vectors
1,000,000 × 1,536 · 10,000 held-out queries
Metric
cosine
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.06x to 1.36x Qdrant's throughput. That range spans the recall levels measured; allowing for the uncertainty in each recall figure widens it to 0.85x to 1.46x.

throughput at equal recall
1.06 to 1.36x
strawmANN over Qdrant, recall@10 0.894 to 0.989
p99 latency at 90% load
strawmANN2.76 ms
Qdrant14.05 ms
W4-sat90, open loop, one offered rate
upload and index build
strawmANN259 s
Qdrant350 s
W1 + W2
peak memory (RSS)
strawmANN36.2 GiB
Qdrant43.6 GiB
largest before the concurrent-write rows (W11); of it, anonymous 4.0 GiB / 3.4 GiB
written to disk
strawmANN63.5 GiB
Qdrant330.8 GiB
before the concurrent-write rows (W11); they wrote 1.4 GiB / 22.0 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 query1,0596271.69x
W4search, saturating (closed loop)3,5723,384parity
W5search batched (16 distinct dataset queries per request)3,542250 requests/s3,441237 requests/sparity
W6quantized: scalar8,1127,1601.13x
W6 ef 32 to 512SQ8 recall control (latency only)2,457 to 24,8082,411 to 17,1551.06 to 1.45x1 of 5 points at parity
W7quantized: binary + oversampling23,26413,5581.72x
W7-2bitquantized: binary quantization, 2 bits + oversampling20,45912,3141.66x
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling21,07712,6851.66x
W8quantized: PQ6,1155,0671.21x
W14-1bitquantized: TurboQuant, 1 bit + oversampling14,06312,6051.12x
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling11,4939,9441.16x
W14-2bitquantized: TurboQuant, 2 bits + oversampling15,83211,5331.37x
W14-4bitquantized: TurboQuant, 4 bits + oversampling12,93710,0061.29x
W9exact / brute force13101.27x
W10 ef 32 to 512recall control (latency only)1,170 to 10,0761,051 to 7,3431.14 to 1.37x1 of 5 points at parity
W12-sel1filtered search, one keyword (~1% of bench12)3,9581,3952.84x
W12-sel10filtered search, any of 10 keywords (~10% of bench12)2,5368353.04x
W12-sel1 ef 32 to 512filtered recall control, one keyword (latency only)3,941 to 3,966552 to 3,8021.70 to 7.16x1 of 5 points not compared recall differs
W12-sel10 ef 32 to 512filtered recall control, any of 10 keywords (latency only)443 to 7,481338 to 2,1601.31 to 3.03x2 of 5 points not compared recall differs
W13scroll / pagination50,41146,3141.09xstrawmANN: 92% is client and socket, not server Qdrant: 82% is client and socket, not server
W11-steadymixed read/write below the rebuild threshold: search bench2 while 49,500 synthetic points append541494-one pass apart: strawmANN pass 1 +15%
W11mixed read/write: search bench2 while 198,000 synthetic points append (runs last)12172-drifted: strawmANN -11% across passes

Throughput by workload

Higher is better. Hatched bars are rows the table does not compare (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.8936Qdrant at ef=32, strawmANN interpolated9,9867,3431.36x1.26 – 1.46x
0.9400strawmANN at ef=64, Qdrant interpolated6,0824,9311.23x1.18 – 1.29x
0.9434Qdrant at ef=64, strawmANN interpolated5,6884,7901.19x1.08 – 1.31x
0.9667strawmANN at ef=128, Qdrant interpolated3,5813,1981.12x1.05 – 1.20x
0.9692Qdrant at ef=128, strawmANN interpolated3,2553,0621.06x0.92 – 1.23x
0.9811strawmANN at ef=256, Qdrant interpolated2,0581,8911.09x0.97 – 1.23x
0.9822Qdrant at ef=256, strawmANN interpolated1,9121,8111.06x0.85 – 1.31x
0.9894strawmANN at ef=512, Qdrant interpolated1,1701,1021.06x0.91 – 1.24x
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.8916strawmANN at ef=32, Qdrant interpolated24,80816,7091.48x1.41 – 1.56x
0.9395strawmANN at ef=64, Qdrant interpolated14,49611,5991.25x1.20 – 1.30x
0.9396Qdrant at ef=64, strawmANN interpolated14,47111,5921.25x1.08 – 1.44x
0.9666strawmANN at ef=128, Qdrant interpolated8,1207,3291.11x1.04 – 1.18x
0.9676Qdrant at ef=128, strawmANN interpolated7,7977,2091.08x0.90 – 1.30x
0.9808strawmANN at ef=256, Qdrant interpolated4,4854,4161.02x0.91 – 1.13x
0.9818Qdrant at ef=256, strawmANN interpolated4,1724,2510.98x0.80 – 1.21x
0.9893strawmANN at ef=512, Qdrant interpolated2,4572,4960.98x0.85 – 1.14x
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, 19,810 to 20,087 across 3 builds in strawmANN and 19,841 to 20,038 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.9699Qdrant at ef=32, strawmANN interpolated4,6302,1602.14x2.01 – 2.29x
0.9728strawmANN at ef=64, Qdrant interpolated4,4332,0192.20x2.02 – 2.39x
0.9893strawmANN at ef=128, Qdrant interpolated2,5171,3801.82x1.73 – 1.92x
0.9901Qdrant at ef=64, strawmANN interpolated2,3551,3541.74x1.46 – 2.07x
0.9959strawmANN at ef=256, Qdrant interpolated1,4689091.62x1.47 – 1.77x
0.9972Qdrant at ef=128, strawmANN interpolated1,0128321.22x0.88 – 1.68x
0.9993Qdrant at ef=256, strawmANN interpolated5465221.05x0.87 – 1.26x
0.9998Qdrant at ef=512, strawmANN interpolated4753381.41x1.26 – 1.57x
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.89660.8928-1.78e-030.89940.8936-1.84e-03
ef=640.93710.9400-8.94e-040.94120.9434-8.80e-04
ef=1280.96630.96670.92904.64e-040.96650.96920.93094.44e-04
ef=2560.98030.98110.96572.61e-040.98160.98220.96782.48e-04
ef=5120.98900.98940.98331.40e-040.99070.99000.98471.33e-04
How recall was measured

10,000 held-out queries, limit 10, ε=9.537e-07, against the fp64 oracle rather than against the other engine. Base checksum 71f1df815731cdbf: 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.00040; Qdrant 0.00049. Over the same builds the engine reported unreachable nodes: strawmANN 0 of 200,000 and 0 of 990,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 query948 µs1.38 ms1.90 ms1.59 ms2.27 ms2.51 ms
W4-sat50 search, fixed rate at 50% of saturation (open loop)1.02 ms1.62 ms1.84 ms1.74 ms2.84 ms3.71 ms
W4-sat70 search, fixed rate at 70% of saturation (open loop)1.11 ms1.93 ms2.28 ms2.00 ms3.79 ms4.76 ms
W4-sat90 search, fixed rate at 90% of saturation (open loop)1.38 ms2.76 ms3.44 ms3.13 ms14.05 ms23.35 ms
W5 search batched (16 distinct dataset queries per request)288.12 ms294.42 ms303.98 ms295.78 ms339.82 ms402.78 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 out17.05 s22.05 s
W1ingest throughput (no index wait)5.46 s34.33 s
W2index build, time to Green253.88 s315.80 s
W6-uploadsearch, SQ8 scalar quantization144.46 s188.44 s
W7-uploadsearch, binary quantization50.14 s171.48 s
W7-2bit-uploadsearch, binary quantization68.18 s134.32 s
W7-1p5bit-uploadsearch, binary quantization66.18 s205.53 s
W8-uploadsearch, product quantization375.31 s886.32 s
W14-1bit-uploadupload259.93 s115.27 s
W14-1p5bit-uploadupload262.94 s159.39 s
W14-2bit-uploadupload260.86 s177.44 s
W14-4bit-uploadupload262.91 s204.51 s
W12-uploadupload39.12 s74.19 s
W1 + W2upload and index, together259.3 s350.1 s1.35x

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 disk35.5 GiBallocated at --capacity26.5 GiB
peak memory (RSS)36.2 GiB43.6 GiB
read from disk74.1 MiB2.6 GiB
written to disk63.5 GiB330.8 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 cf021f3ef3d16b39.

On exact search the two engines' scores differ by at most 3.576e-07 (p99 1.788e-07), against a calibrated absolute ε of 9.537e-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 does not order the engines consistently (0.48x to 2.59x); 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-dbp1m-perf-1008
Qdrant
qd-dbp1m-perf-1008
enginecommit 7be7ce5844f5
ReleaseFast, native build, vnni on
binary sha256 a785c2b080c5d068
built 2026-10-07T15:45:29Z 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-07T19:45:36Z to 2026-10-08T03:57:10Z (3 passes)2026-10-07T21:07:30Z to 2026-10-08T06:01:39Z (3 passes)
profileas-deployed · both engines
§7.1 gatepass · both engines
environment hash373e8531fd3d1bf6 · both engines
load generatorbfb dev @ caaeeef (qdrant/bfb#185, BM25 text requests; carries #183 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 1237500 --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

dbpedia-openai-1m, 1000000 × 1536, cosine, 10000 held-out queries
ground truth: recomputed by our fp64 oracle
26 files, 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: 76.2 GB/s aggregate (24 threads) · 43.1 GB/s single core (57% of bus)
strawmann startup banner, 2026-10-07T19:45:36Z; 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,5643,6151.26x1.26x is 1.74x less work per query x 0.67x cores busy during the row (0.67 against 1.01) x 1.00x clock x 1.09x 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 query1,0596271.69x
W4search, saturating (closed loop)3,5723,384paritywithin the ±5.8% band this dataset's noise floor puts on W4: no measured difference, not a small one
W4-sat50search, fixed rate at 50% of saturation (open loop)1,7321,732offered
W4-sat70search, fixed rate at 70% of saturation (open loop)2,4242,424offered
W4-sat90search, fixed rate at 90% of saturation (open loop)3,1173,117offered
W5search batched (16 distinct dataset queries per request)3,542250 requests/s3,441237 requests/sparityper-batch latency (16 queries/request); queries: dataset, random-sample within the ±5.9% band this dataset's noise floor puts on W5: no measured difference, not a small one batched 16, so qps and rps differ by 16x; the ratio uses qps
W6quantized: scalar8,1127,1601.13x
W6-ef32SQ8 recall control, ef=32 (latency only)24,80817,1551.45x
W6-ef64SQ8 recall control, ef=64 (latency only)14,49611,5921.25x
W6-ef128SQ8 recall control, ef=128 (latency only)8,1207,2091.13x
W6-ef256SQ8 recall control, ef=256 (latency only)4,4854,2511.06x
W6-ef512SQ8 recall control, ef=512 (latency only)2,4572,411paritywithin the ±3.1% band this dataset's noise floor puts on W6-ef512: no measured difference, not a small one
W7quantized: binary + oversampling23,26413,5581.72x
W7-2bitquantized: binary quantization, 2 bits + oversampling20,45912,3141.66x
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling21,07712,6851.66x
W8quantized: PQ6,1155,0671.21x
W14-1bitquantized: TurboQuant, 1 bit + oversampling14,06312,6051.12x
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling11,4939,9441.16x
W14-2bitquantized: TurboQuant, 2 bits + oversampling15,83211,5331.37x
W14-4bitquantized: TurboQuant, 4 bits + oversampling12,93710,0061.29x
W9exact / brute force13101.27x1.27x is 2.53x less work per query x 0.50x cores busy during the row (4.00 against 7.98) x 1.00x clock: the middle term is occupancy, not search speed brute force over the whole collection, no index involved
W10-ef32recall control, ef=32 (latency only)10,0767,3431.37x
W10-ef64recall control, ef=64 (latency only)6,0824,7901.27x
W10-ef128recall control, ef=128 (latency only)3,5813,0621.17x
W10-ef256recall control, ef=256 (latency only)2,0581,8111.14x
W10-ef512recall control, ef=512 (latency only)1,1701,051paritywithin the ±11.6% band this dataset's noise floor puts on W10-ef512: no measured difference, not a small one
W12-sel1filtered search, one keyword (~1% of bench12)3,9581,3952.84xfiltered 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)2,5368353.04xfiltered 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)3,9593,802-recall unequal: 1.0000 vs 0.9829; §7.4 compares at equal recall
W12-sel1-ef64filtered recall control, one keyword, ef=64 (latency only)3,9582,3291.70x
W12-sel1-ef128filtered recall control, one keyword, ef=128 (latency only)3,9411,3982.82x
W12-sel1-ef256filtered recall control, one keyword, ef=256 (latency only)3,9668574.63x
W12-sel1-ef512filtered recall control, one keyword, ef=512 (latency only)3,9565527.16x
W12-sel10-ef32filtered recall control, any of 10 keywords, ef=32 (latency only)7,4812,160-recall unequal: 0.9378 vs 0.9699; §7.4 compares at equal recall
W12-sel10-ef64filtered recall control, any of 10 keywords, ef=64 (latency only)4,4331,354-recall unequal: 0.9728 vs 0.9901; §7.4 compares at equal recall
W12-sel10-ef128filtered recall control, any of 10 keywords, ef=128 (latency only)2,5178323.03x
W12-sel10-ef256filtered recall control, any of 10 keywords, ef=256 (latency only)1,4685222.81x
W12-sel10-ef512filtered recall control, any of 10 keywords, ef=512 (latency only)4433381.31x
W13scroll / pagination50,41146,3141.09xstrawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000) strawmANN: 0.13 ms of the client's 0.14 ms p50 is not server time (13x), so 92% of this row is the load generator and the socket Qdrant: 0.13 ms of the client's 0.16 ms p50 is not server time (6x), so 82% of this row is the load generator and the socket 1.09x is 3.26x less work per query x 0.33x cores busy during the row (1.38 against 4.21) x 1.00x clock x 1.02x counted on-CPU share: the middle term is occupancy, not search speed
W11-steadymixed read/write below the rebuild threshold: search bench2 while 49,500 synthetic points append541494-strawmANN: qps over the 26.1 s of the append the search saw (505 over the whole search); append 1,900 points/s Qdrant: qps over the 26.1 s of the append the search saw (427 over the whole search); append 1,900 points/s strawmANN pass 1 +15% against two passes that agree: one pass set the spread on this row, so a band built from it is not a noise band search-during-write; no recall join
W11mixed read/write: search bench2 while 198,000 synthetic points append (runs last)12172-strawmANN: qps over the 60.0 s of the append the search saw (106 over the whole search); append 3,300 points/s Qdrant: qps over the 186.7 s of the append the search saw (68 over the whole search); append 1,322 points/s strawmANN -11% across its passes, monotonically: the spread on this row is drift rather than noise, so the median is a trend's midpoint and not a repeatable measurement 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 215 µs242 µs262 µs307 µs1.36 ms277 µs319 µs348 µs411 µs1.68 ms
W3search, fp32, single query closed loop 948 µs1.21 ms1.38 ms1.90 ms2.61 ms1.59 ms2.13 ms2.27 ms2.51 ms4.63 ms
W4search, saturating (closed loop) closed loop 17.94 ms19.53 ms20.22 ms24.43 ms37.60 ms18.77 ms24.35 ms33.05 ms44.66 ms75.65 ms
W4-sat50search, fixed rate at 50% of saturation (open loop) open loop 1.02 ms1.37 ms1.62 ms1.84 ms6.31 ms1.74 ms2.38 ms2.84 ms3.71 ms8.84 ms
W4-sat70search, fixed rate at 70% of saturation (open loop) open loop 1.11 ms1.55 ms1.93 ms2.28 ms6.39 ms2.00 ms3.11 ms3.79 ms4.76 ms13.06 ms
W4-sat90search, fixed rate at 90% of saturation (open loop) open loop 1.38 ms2.34 ms2.76 ms3.44 ms7.24 ms3.13 ms6.40 ms14.05 ms23.35 ms40.71 ms
W5search batched (16 distinct dataset queries per request) closed loop 288.12 ms292.48 ms294.42 ms303.98 ms318.36 ms295.78 ms312.32 ms339.82 ms402.78 ms446.41 ms
W6quantized: scalar closed loop 7.90 ms8.48 ms8.72 ms26.73 ms32.37 ms8.80 ms11.14 ms13.85 ms24.76 ms33.84 ms
W6-ef32SQ8 recall control, ef=32 (latency only) closed loop 2.57 ms2.77 ms2.87 ms22.28 ms26.80 ms3.54 ms5.81 ms7.42 ms24.74 ms31.29 ms
W6-ef64SQ8 recall control, ef=64 (latency only) closed loop 4.42 ms4.75 ms4.89 ms19.24 ms23.85 ms5.32 ms7.98 ms9.83 ms23.49 ms30.74 ms
W6-ef128SQ8 recall control, ef=128 (latency only) closed loop 7.90 ms8.48 ms8.71 ms24.79 ms30.67 ms8.76 ms11.15 ms13.74 ms23.13 ms30.92 ms
W6-ef256SQ8 recall control, ef=256 (latency only) closed loop 14.29 ms15.39 ms15.84 ms23.82 ms34.13 ms15.00 ms16.72 ms17.98 ms29.11 ms40.12 ms
W6-ef512SQ8 recall control, ef=512 (latency only) closed loop 26.07 ms28.11 ms28.96 ms29.95 ms42.91 ms26.50 ms29.00 ms30.34 ms41.10 ms51.20 ms
W7quantized: binary + oversampling closed loop 2.72 ms2.86 ms2.94 ms18.45 ms23.64 ms4.16 ms9.36 ms13.00 ms20.16 ms30.03 ms
W7-2bitquantized: binary quantization, 2 bits + oversampling closed loop 3.11 ms3.26 ms3.35 ms14.11 ms17.04 ms4.61 ms10.14 ms13.92 ms26.40 ms43.02 ms
W7-1p5bitquantized: binary quantization, 1.5 bits + oversampling closed loop 3.00 ms3.15 ms3.24 ms25.79 ms29.79 ms4.48 ms9.82 ms13.51 ms23.95 ms33.60 ms
W8quantized: PQ closed loop 10.44 ms11.01 ms11.27 ms26.49 ms34.46 ms12.55 ms13.87 ms15.65 ms24.60 ms35.31 ms
W14-1bitquantized: TurboQuant, 1 bit + oversampling closed loop 4.53 ms4.80 ms4.92 ms15.31 ms20.61 ms4.48 ms10.06 ms14.03 ms25.03 ms35.70 ms
W14-1p5bitquantized: TurboQuant, 1.5 bits + oversampling closed loop 5.55 ms5.87 ms6.03 ms19.45 ms24.95 ms5.88 ms11.74 ms16.09 ms24.04 ms36.46 ms
W14-2bitquantized: TurboQuant, 2 bits + oversampling closed loop 4.02 ms4.23 ms4.34 ms19.09 ms24.08 ms4.93 ms10.70 ms14.78 ms29.95 ms39.38 ms
W14-4bitquantized: TurboQuant, 4 bits + oversampling closed loop 4.92 ms5.23 ms5.37 ms27.84 ms33.86 ms5.79 ms11.84 ms16.51 ms26.39 ms43.46 ms
W9exact / brute force closed loop 620.80 ms798.63 ms825.19 ms836.42 ms836.70 ms810.76 ms836.96 ms848.33 ms878.97 ms926.20 ms
W10-ef32recall control, ef=32 (latency only) closed loop 783 µs1.07 ms1.26 ms1.57 ms5.85 ms1.01 ms1.70 ms2.00 ms2.53 ms5.65 ms
W10-ef64recall control, ef=64 (latency only) closed loop 1.31 ms1.78 ms2.03 ms2.48 ms8.12 ms1.56 ms2.59 ms3.09 ms3.86 ms8.20 ms
W10-ef128recall control, ef=128 (latency only) closed loop 2.23 ms3.09 ms3.47 ms3.89 ms9.45 ms2.54 ms3.93 ms4.62 ms5.73 ms9.55 ms
W10-ef256recall control, ef=256 (latency only) closed loop 3.88 ms5.46 ms6.13 ms6.98 ms12.46 ms4.32 ms6.49 ms7.57 ms9.01 ms13.73 ms
W10-ef512recall control, ef=512 (latency only) closed loop 6.79 ms9.74 ms10.95 ms12.34 ms16.47 ms7.53 ms10.92 ms12.35 ms14.29 ms18.26 ms
W12-sel1filtered search, one keyword (~1% of bench12) closed loop 16.08 ms17.63 ms17.90 ms26.35 ms35.83 ms45.57 ms48.09 ms50.14 ms58.15 ms88.57 ms
W12-sel10filtered search, any of 10 keywords (~10% of bench12) closed loop 25.30 ms26.86 ms27.51 ms32.76 ms50.35 ms76.84 ms81.90 ms84.25 ms98.42 ms143.19 ms
W12-sel1-ef32filtered recall control, one keyword, ef=32 (latency only) closed loop 16.09 ms17.60 ms17.88 ms30.97 ms43.16 ms16.52 ms21.14 ms30.08 ms44.02 ms62.90 ms
W12-sel1-ef64filtered recall control, one keyword, ef=64 (latency only) closed loop 16.10 ms17.59 ms17.85 ms23.13 ms35.14 ms27.30 ms29.06 ms30.88 ms38.66 ms56.92 ms
W12-sel1-ef128filtered recall control, one keyword, ef=128 (latency only) closed loop 16.10 ms17.58 ms17.86 ms52.45 ms60.30 ms45.80 ms48.01 ms49.57 ms56.59 ms83.87 ms
W12-sel1-ef256filtered recall control, one keyword, ef=256 (latency only) closed loop 16.08 ms17.65 ms17.93 ms37.02 ms49.38 ms74.30 ms78.04 ms80.77 ms88.55 ms139.58 ms
W12-sel1-ef512filtered recall control, one keyword, ef=512 (latency only) closed loop 16.13 ms17.59 ms17.84 ms30.91 ms43.62 ms115.60 ms120.15 ms124.34 ms134.45 ms207.08 ms
W12-sel10-ef32filtered recall control, any of 10 keywords, ef=32 (latency only) closed loop 8.51 ms9.11 ms9.45 ms20.99 ms27.49 ms29.69 ms31.92 ms32.99 ms43.04 ms60.45 ms
W12-sel10-ef64filtered recall control, any of 10 keywords, ef=64 (latency only) closed loop 14.46 ms15.39 ms15.77 ms29.24 ms39.57 ms47.13 ms50.72 ms52.55 ms64.03 ms84.94 ms
W12-sel10-ef128filtered recall control, any of 10 keywords, ef=128 (latency only) closed loop 25.52 ms27.09 ms27.65 ms28.54 ms43.96 ms76.99 ms81.98 ms84.22 ms92.99 ms116.41 ms
W12-sel10-ef256filtered recall control, any of 10 keywords, ef=256 (latency only) closed loop 43.72 ms46.10 ms47.08 ms48.66 ms61.75 ms122.27 ms130.02 ms133.88 ms143.82 ms219.01 ms
W12-sel10-ef512filtered recall control, any of 10 keywords, ef=512 (latency only) closed loop 147.64 ms157.26 ms160.17 ms163.18 ms169.77 ms189.02 ms199.45 ms205.24 ms225.01 ms344.10 ms
W13scroll / pagination closed loop 139 µs207 µs233 µs271 µs1.04 ms159 µs222 µs292 µs446 µs2.17 ms
W11-steadymixed read/write below the rebuild threshold: search bench2 while 49,500 synthetic points append closed loop 13.96 ms30.03 ms40.01 ms153.28 ms209.70 ms12.14 ms53.99 ms68.87 ms87.99 ms171.05 ms
W11mixed read/write: search bench2 while 198,000 synthetic points append (runs last) closed loop 58.76 ms168.97 ms196.61 ms225.00 ms252.88 ms115.38 ms196.24 ms230.21 ms371.97 ms836.47 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 disk35.5 GiBbefore W11-steady, W11allocated at --capacity26.5 GiBbefore W11-steady, W11
peak RSS36.2 GiB43.6 GiB
of which anonymous4.0 GiB3.4 GiB
of which file-backed29.8 GiB34.9 GiB
disk read bytes74.1 MiB2.6 GiB
disk write bytes64.9 GiB352.8 GiB
disk read ops56,90769,420
disk write ops1,767,5816,074,116
syscall reads (all fds)12,643,19457,660
syscall writes (all fds)5,276,43039,372,080

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 KiB60.5 MiB3977114.2 MiB383.8 MiB3,0578,306
W000030006
W1180.0 KiB5.7 GiB13510,3894.1 MiB15.7 GiB300261,940
W205.7 GiB093,561172.7 MiB25.5 GiB4,524436,561
W300030000
W400000000
W4-sat5000000000
W4-sat7000000000
W4-sat9000000000
W500000000
W6-upload05.7 GiB093,552225.8 MiB34.4 GiB6,180581,960
W600000000
W6-ef3200000000
W6-ef6400000000
W6-ef12800000000
W6-ef256000000015
W6-ef512000000054
W7-upload12.0 KiB5.7 GiB993,820317.9 MiB37.2 GiB8,214640,505
W700000000
W7-2bit-upload380.0 KiB5.7 GiB28593,550218.6 MiB30.3 GiB5,670521,555
W7-2bit00000000
W7-1p5bit-upload344.0 KiB5.7 GiB25893,550262.7 MiB32.9 GiB6,759568,461
W7-1p5bit00000000
W8-upload92.0 KiB5.7 GiB6994,031175.9 MiB25.3 GiB4,500433,868
W800000000
W14-1bit-upload40.0 KiB5.7 GiB3093,548233.0 MiB30.2 GiB5,982518,948
W14-1bit00000000
W14-1p5bit-upload20.0 KiB5.7 GiB1593,549235.1 MiB30.9 GiB5,991538,858
W14-1p5bit00000000
W14-2bit-upload332.0 KiB5.7 GiB24993,568213.0 MiB30.7 GiB5,394535,263
W14-2bit00000000
W14-4bit-upload24.0 KiB5.7 GiB1893,554216.3 MiB32.1 GiB5,460552,407
W14-4bit00000000
W9000000015
W10-ef3200000000
W10-ef6400000000
W10-ef12800000000
W10-ef25600000000
W10-ef51200000000
W12-upload768.0 KiB1.1 GiB576796,30653.5 MiB5.3 GiB1,49492,031
W12-sel10003000438
W12-sel1012.0 KiB094500069
W12-sel1-ef32000330000
W12-sel1-ef64000000048
W12-sel1-ef12888.0 KiB066000081
W12-sel1-ef256000000066
W12-sel1-ef51200000000
W12-sel10-ef3200000000
W12-sel10-ef64000240000
W12-sel10-ef128000450000
W12-sel10-ef256000540000
W12-sel10-ef51200000000
W1300000000
W11-steady64.4 MiB290.1 MiB49,4524,68973.6 MiB12.2 GiB1,809210,007
W117.5 MiB1.1 GiB5,73318,727167.0 MiB9.8 GiB4,086172,654
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-upload111.0 s541%43.2 ms51,993 / 5772113,520 / 09 1%158.5 s495%15,024.7 ms155,135 / 34,83912,858424,958 / 193,87842 7%
W07.7 s70%3.0 ms164,728 / 3900 / 0914.2 s102%3.7 ms561,018 / 18197464 / 036 0%
W111.5 s137%107.4 ms587,441 / 2401,576,572 / 09260.1 s711%108,197.3 ms158,131 / 88,92331,954630,876 / 1,597,61953 68%
W22,022.1 s771%1,260.2 ms596,502 / 9,18001,640,235 / 09 1%2,115.7 s596%108,969.3 ms197,060 / 102,05532,7011,414,315 / 1,626,49038 3%
W343.6 s92%4.9 ms192,393 / 5500 / 0979.5 s100%5.9 ms562,653 / 2422281,385 / 038 0%
W4100.3 s715%7.0 ms89,883 / 970119 / 09117.4 s792%96,311.0 ms42,815 / 43,1205,04730,332 / 044 0%
W4-sat50190.5 s165%17.1 ms546,259 / 12403 / 09351.1 s304%11,591.5 ms1,936,534 / 9,832469,2704,655 / 052 0%
W4-sat70206.3 s250%21.2 ms481,356 / 122012 / 09381.6 s462%74,808.3 ms1,660,735 / 50,690648,1543,791 / 068
W4-sat90270.9 s421%13.1 ms444,623 / 15609 / 09444.9 s692%217,282.7 ms743,500 / 186,940286,32125,140 / 044 0%
W599.7 s706%9.7 ms6,586 / 2040752 / 09115.8 s796%86,320.1 ms10,060 / 16,5251,55222,143 / 044 0%
W6-upload1,106.8 s714%467.4 ms94,346 / 4,94002,205,991 / 09 1%1,048.0 s434%65,433.9 ms222,909 / 63,21130,2532,981,965 / 1,686,60941 0%
W644.9 s723%6.8 ms80,702 / 77018 / 0955.0 s784%15,840.5 ms36,076 / 25,0292,6072,779 / 046 65%
W6-ef3215.5 s753%1.6 ms34,950 / 1706 / 0922.2 s750%12,726.4 ms27,488 / 10,7205,947438 / 046
W6-ef6425.8 s737%2.0 ms60,525 / 3000 / 0933.7 s772%14,418.4 ms27,201 / 14,2844,624205 / 046
W6-ef12844.9 s725%2.7 ms80,921 / 4900 / 0955.1 s790%15,464.4 ms31,248 / 23,7762,507721 / 046
W6-ef25680.0 s715%7.6 ms96,652 / 110050 / 0993.9 s796%18,336.9 ms33,558 / 29,7024821,416 / 046
W6-ef512144.6 s709%8.1 ms108,115 / 18405 / 09165.7 s797%27,282.8 ms41,911 / 39,6444242,482 / 046
W7-upload288.9 s487%148.7 ms96,206 / 1,44511,698,301 / 09 3%608.6 s165%39,248.8 ms306,147 / 35,27327,9242,997,835 / 1,861,54041 0%
W716.2 s741%1.5 ms55,285 / 20045 / 0928.6 s767%93,182.8 ms77,152 / 53,63119,5234,456 / 081
W7-2bit-upload312.3 s406%170.2 ms92,859 / 1,54531,756,298 / 119 2%636.3 s363%44,457.0 ms234,126 / 40,37929,7492,162,663 / 1,824,78247 7%
W7-2bit18.4 s740%2.3 ms59,034 / 2500 / 0931.4 s766%93,687.6 ms74,566 / 54,14919,4253,632 / 087
W7-1p5bit-upload298.1 s397%143.3 ms95,767 / 1,54261,736,859 / 29 3%627.1 s245%46,578.9 ms252,830 / 41,92327,6652,437,715 / 1,816,14146 20%
W7-1p5bit17.8 s736%2.0 ms58,181 / 2300 / 0930.6 s768%93,526.9 ms74,150 / 55,11819,7002,705 / 086
W8-upload2,968.7 s769%1,353.4 ms105,755 / 13,53601,859,672 / 09 0%5,981.8 s652%27,983.8 ms657,619 / 156,783100,5041,707,263 / 1,611,18743 0%
W858.8 s713%3.4 ms108,957 / 7400 / 0978.7 s794%15,653.6 ms35,300 / 28,6476503,577 / 049
W14-1bit-upload2,059.2 s766%1,109.5 ms93,003 / 8,92611,708,495 / 19 0%650.8 s368%54,863.8 ms255,078 / 78,54535,2302,151,305 / 1,777,60247 12%
W14-1bit26.2 s730%2.0 ms82,975 / 3500 / 0930.8 s769%94,570.4 ms71,672 / 51,01718,6355,125 / 085
W14-1p5bit-upload2,082.3 s766%1,126.5 ms94,130 / 9,23811,739,075 / 09 0%849.4 s354%53,287.1 ms258,560 / 87,85929,5372,294,444 / 1,803,17146 18%
W14-1p5bit31.9 s726%2.9 ms90,188 / 4100 / 0939.1 s771%97,130.4 ms61,299 / 45,92617,0666,949 / 084
W14-2bit-upload2,059.1 s764%1,112.1 ms96,300 / 9,16101,772,660 / 09 0%989.6 s390%72,137.4 ms241,792 / 115,52433,2082,223,495 / 1,827,48047 10%
W14-2bit23.5 s734%2.5 ms75,301 / 3600 / 0933.6 s767%94,664.6 ms68,675 / 51,31219,4444,576 / 085 13%
W14-4bit-upload2,071.0 s762%1,135.9 ms95,546 / 9,15811,900,954 / 29 0%1,050.4 s327%62,528.4 ms306,032 / 211,67633,5662,695,357 / 1,919,68747 18%
W14-4bit28.4 s728%2.2 ms81,154 / 3700 / 0938.9 s772%97,214.2 ms62,007 / 47,27516,3534,632 / 085
W9636.2 s400%71.2 ms10,366 / 1,82400 / 091,612.5 s798%14,216.7 ms26,586 / 22,8026,6411,513 / 049
W10-ef3234.7 s694%4.0 ms97,500 / 5000 / 0940.3 s589%14,951.6 ms247,892 / 24,10184,2161,035 / 049
W10-ef6458.1 s704%5.9 ms103,016 / 7500 / 0966.3 s633%41,212.9 ms307,642 / 46,407157,577535 / 066 0%
W10-ef12898.9 s706%9.6 ms108,882 / 14000 / 09108.4 s662%57,485.6 ms338,258 / 55,003177,203472 / 066
W10-ef256171.9 s706%17.3 ms113,368 / 26000 / 09190.4 s689%83,088.3 ms370,980 / 83,785196,685904 / 066
W10-ef512301.4 s704%24.7 ms116,256 / 50800 / 09338.6 s711%92,337.9 ms340,069 / 97,355146,1492,196 / 049 0%
W12-upload299.7 s614%181.1 ms32,443 / 1,4980453,100 / 419 2%473.9 s571%17,205.5 ms52,358 / 17,8426,853346,436 / 446,59951 0%
W12-sel190.0 s710%6.6 ms36,245 / 144048 / 09286.5 s799%39,910.4 ms57,181 / 57,6744714,266 / 058
W12-sel10139.8 s708%8.3 ms122,727 / 18506 / 29478.6 s798%57,403.3 ms76,468 / 75,6121,1056,255 / 058
W12-sel1-ef3289.8 s709%7.2 ms33,099 / 11900 / 09104.7 s793%68,961.4 ms36,826 / 37,1312,67219,528 / 058 86%
W12-sel1-ef6490.1 s710%6.1 ms46,408 / 12400 / 09171.6 s798%27,271.3 ms42,807 / 40,8703032,525 / 058
W12-sel1-ef12890.0 s707%6.1 ms41,290 / 144013 / 109285.9 s798%39,808.4 ms57,043 / 55,6935503,145 / 058
W12-sel1-ef25689.9 s709%6.2 ms41,961 / 138054 / 09466.5 s799%54,864.6 ms75,336 / 74,1961,1776,221 / 058
W12-sel1-ef51290.2 s711%5.4 ms43,063 / 11400 / 09723.8 s799%68,963.1 ms92,603 / 92,5252,3748,405 / 058
W12-sel10-ef3248.2 s717%2.3 ms100,250 / 4900 / 09185.2 s799%29,128.7 ms44,729 / 42,7733033,330 / 058
W12-sel10-ef6480.7 s713%3.7 ms113,741 / 8900 / 09294.3 s796%41,081.1 ms58,550 / 56,9515454,735 / 058
W12-sel10-ef128141.0 s708%5.0 ms124,440 / 13500 / 09479.6 s797%57,549.0 ms75,509 / 75,1091,0425,123 / 058
W12-sel10-ef256240.2 s704%11.3 ms132,489 / 28603 / 09765.9 s800%74,054.5 ms97,165 / 97,0262,86210,499 / 058
W12-sel10-ef512796.9 s706%70.1 ms68,835 / 1,37700 / 091,183.0 s799%87,860.9 ms115,762 / 116,9085,85415,545 / 058
W135.6 s137%4.6 ms245,377 / 600 / 099.2 s411%812.8 ms383,390 / 4,583113,205677 / 073
W11-steady256.2 s784%195,850.3 ms52,523 / 87,295779485,661 / 15,72018 44%252.7 s773%212,991.1 ms117,319 / 94,77144,937652,509 / 127,90465 90%
W11603.3 s802%506,643.3 ms24,151 / 125,2881,011769,326 / 1,13319 71%1,488.1 s794%1,211,680.4 ms200,009 / 358,59337,0461,053,039 / 352,43659 68%
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. 38 rows never stalled on I/O and are not drawn.

Time stalled on memory

Time every task in the engine's cgroup was stalled on memory. Lower is better. 52 rows never stalled on memory and are not drawn.

workloadstrawmANNQdrant
waitingblocked on diskcpu some/fullio some/fullmemory some/fullwaitingblocked on diskcpu some/fullio some/fullmemory some/full
W0-upload43.2 ms0 ms14 / 9 ms1 / 1 ms0 / 0 ms15,024.7 ms0 ms1,372 / 16 ms65 / 63 ms0 / 0 ms
W03.0 ms0 ms47 / 47 ms0 / 0 ms0 / 0 ms3.7 ms0 ms78 / 78 ms0 / 0 ms0 / 0 ms
W1107.4 ms0 ms53 / 53 ms42 / 42 ms0 / 0 ms108,197.3 ms0 ms9,400 / 26 ms716 / 224 ms0 / 0 ms
W21,260.2 ms0 ms194 / 79 ms10 / 10 ms0 / 0 ms108,969.3 ms0 ms9,440 / 85 ms24,405 / 23,623 ms0 / 0 ms
W34.9 ms0 ms40 / 40 ms0 / 0 ms0 / 0 ms5.9 ms0 ms102 / 102 ms0 / 0 ms0 / 0 ms
W47.0 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms96,311.0 ms0 ms5,124 / 2 ms0 / 0 ms0 / 0 ms
W4-sat5017.1 ms0 ms156 / 156 ms0 / 0 ms0 / 0 ms11,591.5 ms0 ms1,634 / 271 ms0 / 0 ms0 / 0 ms
W4-sat7021.2 ms0 ms156 / 156 ms0 / 0 ms0 / 0 ms74,808.3 ms0 ms8,194 / 219 ms0 / 0 ms0 / 0 ms
W4-sat9013.1 ms0 ms151 / 151 ms0 / 0 ms0 / 0 ms217,282.7 ms0 ms18,988 / 93 ms0 / 0 ms0 / 0 ms
W59.7 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms86,320.1 ms0 ms3,976 / 1 ms0 / 0 ms0 / 0 ms
W6-upload467.4 ms0 ms76 / 31 ms1 / 1 ms0 / 0 ms65,433.9 ms0 ms5,991 / 79 ms36,586 / 34,486 ms0 / 0 ms
W66.8 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms15,840.5 ms0 ms1,759 / 2 ms0 / 0 ms0 / 0 ms
W6-ef321.6 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms12,726.4 ms0 ms1,387 / 2 ms0 / 0 ms0 / 0 ms
W6-ef642.0 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms14,418.4 ms0 ms1,509 / 2 ms0 / 0 ms0 / 0 ms
W6-ef1282.7 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms15,464.4 ms0 ms1,686 / 1 ms0 / 0 ms0 / 0 ms
W6-ef2567.6 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms18,336.9 ms0 ms2,176 / 1 ms0 / 0 ms0 / 0 ms
W6-ef5128.1 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms27,282.8 ms0 ms3,372 / 1 ms0 / 0 ms0 / 0 ms
W7-upload148.7 ms0 ms38 / 28 ms38 / 38 ms104 / 104 ms39,248.8 ms0 ms3,633 / 148 ms181,334 / 176,519 ms0 / 0 ms
W71.5 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms93,182.8 ms0 ms3,310 / 3 ms0 / 0 ms0 / 0 ms
W7-2bit-upload170.2 ms0 ms43 / 28 ms53 / 53 ms0 / 0 ms44,457.0 ms0 ms4,123 / 85 ms14,994 / 13,827 ms0 / 0 ms
W7-2bit2.3 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms93,687.6 ms0 ms3,440 / 3 ms0 / 0 ms0 / 0 ms
W7-1p5bit-upload143.3 ms0 ms51 / 29 ms72 / 72 ms0 / 0 ms46,578.9 ms0 ms4,157 / 104 ms79,114 / 77,860 ms0 / 0 ms
W7-1p5bit2.0 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms93,526.9 ms0 ms3,395 / 3 ms0 / 0 ms0 / 0 ms
W8-upload1,353.4 ms0 ms183 / 45 ms61 / 61 ms753 / 753 ms27,983.8 ms0 ms6,799 / 314 ms18,380 / 14,853 ms0 / 0 ms
W83.4 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms15,653.6 ms0 ms1,873 / 1 ms0 / 0 ms0 / 0 ms
W14-1bit-upload1,109.5 ms0 ms152 / 41 ms69 / 69 ms0 / 0 ms54,863.8 ms0 ms5,102 / 97 ms16,034 / 15,307 ms0 / 0 ms
W14-1bit2.0 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms94,570.4 ms0 ms3,416 / 3 ms0 / 0 ms0 / 0 ms
W14-1p5bit-upload1,126.5 ms0 ms153 / 40 ms41 / 41 ms0 / 0 ms53,287.1 ms0 ms5,201 / 108 ms26,373 / 25,216 ms0 / 0 ms
W14-1p5bit2.9 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms97,130.4 ms0 ms3,715 / 3 ms0 / 0 ms0 / 0 ms
W14-2bit-upload1,112.1 ms0 ms152 / 42 ms43 / 43 ms0 / 0 ms72,137.4 ms0 ms6,745 / 93 ms18,667 / 17,541 ms0 / 0 ms
W14-2bit2.5 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms94,664.6 ms0 ms3,524 / 3 ms0 / 0 ms0 / 0 ms
W14-4bit-upload1,135.9 ms0 ms155 / 40 ms54 / 54 ms0 / 0 ms62,528.4 ms0 ms6,106 / 131 ms65,932 / 63,445 ms0 / 0 ms
W14-4bit2.2 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms97,214.2 ms0 ms3,737 / 3 ms0 / 0 ms0 / 0 ms
W971.2 ms0 ms18 / 18 ms0 / 0 ms0 / 0 ms14,216.7 ms0 ms1,639 / 37 ms0 / 0 ms0 / 0 ms
W10-ef324.0 ms0 ms11 / 11 ms0 / 0 ms0 / 0 ms14,951.6 ms0 ms1,759 / 23 ms0 / 0 ms0 / 0 ms
W10-ef645.9 ms0 ms10 / 10 ms0 / 0 ms0 / 0 ms41,212.9 ms0 ms3,902 / 31 ms0 / 0 ms0 / 0 ms
W10-ef1289.6 ms0 ms9 / 9 ms0 / 0 ms0 / 0 ms57,485.6 ms0 ms5,598 / 33 ms0 / 0 ms0 / 0 ms
W10-ef25617.3 ms0 ms8 / 8 ms0 / 0 ms0 / 0 ms83,088.3 ms0 ms8,517 / 37 ms0 / 0 ms0 / 0 ms
W10-ef51224.7 ms0 ms7 / 7 ms0 / 0 ms0 / 0 ms92,337.9 ms0 ms10,244 / 67 ms0 / 0 ms0 / 0 ms
W12-upload181.1 ms0 ms38 / 24 ms63 / 63 ms4,928 / 4,928 ms17,205.5 ms0 ms1,673 / 22 ms212 / 136 ms0 / 0 ms
W12-sel16.6 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms39,910.4 ms0 ms4,975 / 2 ms0 / 0 ms0 / 0 ms
W12-sel108.3 ms0 ms2 / 2 ms3 / 3 ms0 / 0 ms57,403.3 ms0 ms7,160 / 3 ms0 / 0 ms0 / 0 ms
W12-sel1-ef327.2 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms68,961.4 ms0 ms3,902 / 1 ms0 / 0 ms0 / 0 ms
W12-sel1-ef646.1 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms27,271.3 ms0 ms3,364 / 1 ms0 / 0 ms0 / 0 ms
W12-sel1-ef1286.1 ms0 ms2 / 2 ms2 / 2 ms0 / 0 ms39,808.4 ms0 ms4,957 / 2 ms0 / 0 ms0 / 0 ms
W12-sel1-ef2566.2 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms54,864.6 ms0 ms6,844 / 3 ms0 / 0 ms0 / 0 ms
W12-sel1-ef5125.4 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms68,963.1 ms0 ms8,609 / 5 ms0 / 0 ms0 / 0 ms
W12-sel10-ef322.3 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms29,128.7 ms0 ms3,616 / 1 ms0 / 0 ms0 / 0 ms
W12-sel10-ef643.7 ms0 ms3 / 3 ms0 / 0 ms0 / 0 ms41,081.1 ms0 ms5,115 / 2 ms0 / 0 ms0 / 0 ms
W12-sel10-ef1285.0 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms57,549.0 ms0 ms7,182 / 3 ms0 / 0 ms0 / 0 ms
W12-sel10-ef25611.3 ms0 ms2 / 2 ms0 / 0 ms0 / 0 ms74,054.5 ms0 ms9,245 / 5 ms0 / 0 ms0 / 0 ms
W12-sel10-ef51270.1 ms0 ms18 / 18 ms0 / 0 ms0 / 0 ms87,860.9 ms0 ms10,967 / 8 ms0 / 0 ms0 / 0 ms
W134.6 ms0 ms29 / 29 ms0 / 0 ms0 / 0 ms812.8 ms0 ms118 / 27 ms0 / 0 ms0 / 0 ms
W11-steady195,850.3 ms0 ms25,581 / 7 ms691 / 147 ms0 / 0 ms212,991.1 ms0 ms20,494 / 34 ms141 / 28 ms0 / 0 ms
W11506,643.3 ms0 ms62,796 / 12 ms91 / 24 ms0 / 0 ms1,211,680.4 ms0 ms129,757 / 65 ms1,819 / 203 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.502.011.006x nominal5.34---1.292.011.006x nominal4.53---
W01.382.011.005x nominal5.31256,2416.8 KiB984.01.222.011.006x nominal3.12445,64937.7 KiB1,139.6
W12.122.011.006x nominal0.70---1.072.011.008x nominal1.24---
W20.412.011.008x nominal2.37---0.602.011.007x nominal1.71---
W30.712.011.006x nominal3.921,676,5465,752.4 KiB4,252.40.692.011.007x nominal1.933,042,9294,543.4 KiB6,071.3
W40.302.011.008x nominal3.214,012,2314,265.0 KiB4,064.90.422.011.007x nominal2.024,665,6214,252.6 KiB5,266.6
W4-sat500.652.011.007x nominal3.901,847,3445,418.8 KiB4,202.30.622.011.007x nominal2.203,357,8614,475.4 KiB6,031.0
W4-sat700.592.011.008x nominal3.912,033,8795,071.9 KiB4,166.30.572.011.007x nominal2.273,676,1784,410.4 KiB5,936.2
W4-sat900.442.011.007x nominal3.822,708,2924,439.6 KiB4,151.70.472.011.008x nominal2.324,341,4564,348.9 KiB5,595.0
W50.282.011.008x nominal3.344,003,6624,316.6 KiB4,012.40.392.011.007x nominal2.004,631,4614,215.1 KiB5,060.4
W6-upload0.862.011.007x nominal2.06---1.742.011.008x nominal1.44---
W60.572.011.008x nominal4.101,789,4012,714.7 KiB5,737.51.232.011.008x nominal1.612,179,803836.4 KiB4,131.9
W6-ef320.672.011.007x nominal2.70613,693839.4 KiB1,872.61.362.011.007x nominal1.32871,491299.1 KiB1,603.1
W6-ef640.612.011.008x nominal3.421,023,9751,492.8 KiB3,174.21.292.011.007x nominal1.451,330,144487.6 KiB2,491.1
W6-ef1280.572.011.007x nominal4.111,788,2622,716.0 KiB5,737.51.222.011.008x nominal1.622,183,417833.1 KiB4,119.7
W6-ef2560.562.011.007x nominal4.753,196,1794,951.6 KiB10,828.11.182.011.007x nominal1.773,737,6421,477.9 KiB6,999.0
W6-ef5120.562.011.008x nominal5.345,791,6199,039.9 KiB21,074.31.152.011.009x nominal1.926,616,7852,703.4 KiB12,148.0
W7-upload1.332.011.007x nominal6.13---2.112.011.006x nominal4.58---
W71.312.011.008x nominal6.58641,434421.5 KiB2,986.21.472.011.007x nominal3.501,082,919461.8 KiB3,366.8
W7-2bit-upload1.262.011.006x nominal5.79---1.932.011.007x nominal4.08---
W7-2bit1.232.011.007x nominal5.99726,849435.7 KiB3,124.11.392.011.007x nominal3.321,192,431474.9 KiB3,416.8
W7-1p5bit-upload1.292.011.006x nominal5.99---2.002.011.007x nominal4.27---
W7-1p5bit1.242.011.007x nominal6.22704,491431.1 KiB3,106.41.412.011.007x nominal3.421,159,883472.6 KiB3,454.7
W8-upload2.312.011.007x nominal0.73---5.402.011.006x nominal0.17---
W84.332.011.006x nominal0.522,341,563445.2 KiB3,731.23.242.011.006x nominal0.493,124,364514.6 KiB4,069.6
W14-1bit-upload0.512.011.007x nominal1.87---2.532.011.007x nominal2.08---
W14-1bit2.092.011.007x nominal2.071,039,966435.2 KiB4,288.11.612.011.006x nominal2.431,171,852445.9 KiB2,961.7
W14-1p5bit-upload0.572.011.007x nominal1.71---2.382.011.007x nominal1.68---
W14-1p5bit2.272.011.007x nominal1.581,263,192444.2 KiB4,499.81.492.011.006x nominal2.041,514,098506.8 KiB3,115.5
W14-2bit-upload0.522.011.007x nominal1.87---2.902.011.007x nominal1.09---
W14-2bit1.832.011.007x nominal2.59927,706440.6 KiB4,552.61.562.011.007x nominal2.221,284,774467.8 KiB3,258.4
W14-4bit-upload0.542.011.007x nominal1.84---2.632.011.007x nominal1.07---
W14-4bit1.552.011.009x nominal2.441,128,835492.6 KiB5,011.21.392.011.007x nominal2.161,501,938491.6 KiB3,675.9
W90.582.011.008x nominal0.15639,305,597798,578.5 KiB629,566.00.362.011.008x nominal0.091,620,243,551490,680.2 KiB1,078,523.6
W10-ef320.352.011.008x nominal2.321,375,0441,410.3 KiB1,541.60.632.011.008x nominal1.941,543,1021,535.4 KiB2,355.9
W10-ef640.322.011.008x nominal2.872,316,0202,432.8 KiB2,557.10.552.011.007x nominal2.242,513,8412,534.9 KiB3,597.3
W10-ef1280.302.011.007x nominal3.223,953,5544,204.2 KiB4,489.30.512.011.007x nominal2.324,167,4314,284.8 KiB5,705.7
W10-ef2560.302.011.008x nominal3.556,882,4347,410.0 KiB8,274.50.452.011.007x nominal2.507,429,8197,585.2 KiB9,387.8
W10-ef5120.302.011.009x nominal3.8912,106,01113,186.5 KiB15,818.50.422.011.008x nominal2.7913,402,27813,528.1 KiB15,758.4
W12-upload0.522.011.009x nominal2.43---0.762.011.007x nominal1.95---
W12-sel10.272.011.007x nominal2.453,614,9606,183.6 KiB4,603.61.862.011.007x nominal3.7411,454,6433,279.4 KiB4,834.9
W12-sel100.852.011.008x nominal3.625,599,4768,230.0 KiB10,628.81.592.011.007x nominal2.7619,156,8078,694.8 KiB12,206.2
W12-sel1-ef320.272.011.009x nominal2.513,616,7286,185.7 KiB4,607.71.752.011.007x nominal2.714,162,7831,529.5 KiB2,376.0
W12-sel1-ef640.272.011.009x nominal2.453,617,2236,177.0 KiB4,603.51.822.011.008x nominal3.216,853,7312,237.2 KiB3,366.3
W12-sel1-ef1280.272.011.009x nominal2.473,622,8896,174.3 KiB4,595.51.862.011.009x nominal3.7411,457,6593,257.1 KiB4,952.8
W12-sel1-ef2560.272.011.009x nominal2.463,615,0546,176.1 KiB4,602.51.902.021.010x nominal4.1618,707,8774,492.1 KiB6,906.8
W12-sel1-ef5120.272.021.010x nominal2.463,625,8366,172.9 KiB4,611.71.992.021.010x nominal4.3829,074,8555,728.6 KiB9,008.0
W12-sel10-ef320.942.011.008x nominal2.721,921,8122,753.6 KiB3,373.21.572.011.007x nominal2.147,385,5433,454.1 KiB4,876.3
W12-sel10-ef640.872.011.007x nominal3.243,221,2524,710.9 KiB5,878.91.582.011.007x nominal2.4311,795,5395,453.3 KiB7,664.1
W12-sel10-ef1280.842.011.007x nominal3.635,641,4648,251.3 KiB10,630.81.582.011.007x nominal2.7619,228,1988,669.6 KiB12,227.3
W12-sel10-ef2560.882.011.007x nominal3.879,634,46314,014.7 KiB19,192.01.592.011.007x nominal3.1230,640,77913,532.4 KiB19,340.6
W12-sel10-ef5120.252.011.009x nominal0.7532,006,99738,879.8 KiB38,130.11.612.011.006x nominal3.4947,360,20220,298.6 KiB29,442.9
W131.362.011.008x nominal1.2942,5741.0 KiB13.51.462.021.010x nominal1.47138,8351.4 KiB39.2
W11-steady0.322.011.007x nominal1.8330,774,18636,870.4 KiB25,006.20.662.011.007x nominal0.6735,068,82216,210.2 KiB34,486.1
W110.292.011.007x nominal1.10149,880,481177,081.7 KiB95,234.70.512.011.007x nominal0.49244,593,270118,339.6 KiB239,539.1

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. strawmANN: perf and /proc disagree on minor faults by up to 14% on W12-upload; strawmANN: perf and /proc disagree on context switches by up to 7% on W11-steady; Qdrant: perf and /proc disagree on minor faults by up to 43% on W1, W2, W6-upload, W7-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 70% 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- / 1990,000990,000416100-1cached
bench11 / 5- / 5- / 1990,0000 / 59,5001,53616100-1cached
bench21 / 2- / 1- / 1990,000990,0001,53616100-1cached
bench61 / 2- / 1- / 1990,000990,0001,53616100scalar1cached
bench71 / 2- / 1- / 1990,000990,0001,53616100binary1cached
bench7b21 / 2- / 1- / 1990,000990,0001,53616100binary1cached
bench7b151 / 2- / 1- / 1990,000990,0001,53616100binary1cached
bench81 / 2- / 1- / 1990,000990,0001,53616100product1cached
bench14t11 / 2- / 1- / 1990,000990,0001,53616100turboquant1cached
bench14t151 / 2- / 1- / 1990,000990,0001,53616100turboquant1cached
bench14t21 / 2- / 1- / 1990,000990,0001,53616100turboquant1cached
bench14t41 / 2- / 1- / 1990,000990,0001,53616100turboquant1cached
bench121 / 2- / 1- / 1200,000200,0001,53616100-1cached

After the mutating rows bench2 held strawmANN 1,237,500 (+247,500), 1,075,740 of them indexed; Qdrant 1,237,500 (+247,500), 1,085,700 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=990,000
metricstrawmANNQdrant
wall clock20.5 s32.0 s1.56x
of which upload1.4 s7.8 s5.55x
of which index wait17.1 s22.1 s1.29x
time to Green17.1 s22.1 s1.29x
cpu111.0 s158.5 s1.43x
cpu, % of wall541%495%
waiting for a core43.2 ms15,024.7 ms347.40x
migrations212,8586,429.00x
faults min/maj113,520 / 0424,958 / 193,878
peak RSS441.1 MiB1.4 GiB3.30x
disk written60.5 MiB383.8 MiB
disk read4.0 KiB114.2 MiB

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

closed-loop · collection=bench0 · client -p 1 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second4,5643,6151.26x
client p50215 µs277 µs1.29x
client p99262 µs348 µs1.33x
client p99.9307 µs411 µs1.34x
server p50123 µs174 µs1.41x
server p99135 µs218 µs1.62x
wall clock11.0 s13.9 s1.26x
queries sent50,00050,000
cpu7.7 s14.2 s1.83x
cpu, % of wall70%102%
waiting for a core3.0 ms3.7 ms1.24x
migrations0197
faults min/maj0 / 0464 / 0
peak RSS441.1 MiB1.4 GiB3.30x
disk written00
disk read00
1.26x is 1.74x less work per query x 0.67x cores busy during the row (0.67 against 1.01) x 1.00x clock x 1.09x 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=990,000
metricstrawmANNQdrant
wall clock8.4 s36.6 s4.35x
of which upload5.5 s34.3 s6.29x
cpu11.5 s260.1 s22.52x
cpu, % of wall137%711%
waiting for a core107.4 ms108,197.3 ms1,007.29x
migrations031,954
faults min/maj1,576,572 / 0630,876 / 1,597,619
peak RSS7.6 GiB11.5 GiB1.51x
disk written5.7 GiB15.7 GiB
disk read180.0 KiB4.1 MiB

W2 index build time

upload · collection=bench2 · client -p 8 -t 8 -c 1 (-c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock262.2 s355.1 s1.35x
of which upload5.5 s37.0 s6.76x
of which index wait253.9 s315.8 s1.24x
time to Green253.9 s315.8 s1.24x
cpu2,022.1 s2,115.7 s1.05x
cpu, % of wall771%596%
waiting for a core1,260.2 ms108,969.3 ms86.47x
migrations032,701
faults min/maj1,640,235 / 01,414,315 / 1,626,490
peak RSS7.9 GiB22.6 GiB2.87x
disk written5.7 GiB25.5 GiB
disk read0172.7 MiB

W3 search, fp32, single query 1.69x

ef=128 · closed-loop · collection=bench2 · client -p 1 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second1,0596271.69x
recall@100.96670.9692~equal
client p50948 µs1.59 ms1.68x
client p991.38 ms2.27 ms1.65x
client p99.91.90 ms2.51 ms1.32x
server p50846 µs1.45 ms1.71x
server p991.27 ms2.11 ms1.67x
wall clock47.2 s79.7 s1.69x
queries sent50,00050,000
cpu43.6 s79.5 s1.82x
cpu, % of wall92%100%
waiting for a core4.9 ms5.9 ms1.21x
migrations0228
faults min/maj0 / 01,385 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00

W4 search, saturating (closed loop) parity

ef=128 · closed-loop · collection=bench2 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,5723,384parity
recall@100.96670.9692~equal
client p5017.94 ms18.77 ms1.05x
client p9920.22 ms33.05 ms1.63x
client p99.924.43 ms44.66 ms1.83x
server p5017.83 ms18.22 ms1.02x
server p9920.06 ms27.99 ms1.39x
wall clock14.0 s14.8 s1.06x
queries sent50,00050,000
cpu100.3 s117.4 s1.17x
cpu, % of wall715%792%
waiting for a core7.0 ms96,311.0 ms13,694.37x
migrations05,047
faults min/maj119 / 030,332 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00
within the ±5.8% band this dataset's noise floor puts on W4: no measured difference, not a small one

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

ef=128 · open-loop · offered=1,732/s (50% of saturation, pinned reference 3,463 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second1,7321,732offered
recall@100.96670.9692~equal
client p501.02 ms1.74 ms1.70x
client p991.62 ms2.84 ms1.76x
client p99.91.84 ms3.71 ms2.02x
server p50920 µs1.59 ms1.73x
server p991.51 ms2.63 ms1.75x
wall clock115.6 s115.6 s~equal
queries sent200,000200,000
cpu190.5 s351.1 s1.84x
cpu, % of wall165%304%
waiting for a core17.1 ms11,591.5 ms679.75x
migrations0469,270
faults min/maj3 / 04,655 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00

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

ef=128 · open-loop · offered=2,424/s (70% of saturation, pinned reference 3,463 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second2,4242,424offered
recall@100.96670.9692~equal
client p501.11 ms2.00 ms1.81x
client p991.93 ms3.79 ms1.96x
client p99.92.28 ms4.76 ms2.09x
server p501.00 ms1.82 ms1.82x
server p991.82 ms3.46 ms1.90x
wall clock82.6 s82.6 s~equal
queries sent200,000200,000
cpu206.3 s381.6 s1.85x
cpu, % of wall250%462%
waiting for a core21.2 ms74,808.3 ms3,531.15x
migrations0648,154
faults min/maj12 / 03,791 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00

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

ef=128 · open-loop · offered=3,117/s (90% of saturation, pinned reference 3,463 qps) · collection=bench2 · client -p n/a under --rps -t 16 -c 2 · n=200,000
metricstrawmANNQdrant
queries/second3,1173,117offered
recall@100.96670.9692~equal
client p501.38 ms3.13 ms2.27x
client p992.76 ms14.05 ms5.10x
client p99.93.44 ms23.35 ms6.78x
server p501.27 ms2.70 ms2.13x
server p992.63 ms10.43 ms3.96x
wall clock64.3 s64.3 s~equal
queries sent200,000200,000
cpu270.9 s444.9 s1.64x
cpu, % of wall421%692%
waiting for a core13.1 ms217,282.7 ms16,580.49x
migrations0286,321
faults min/maj9 / 025,140 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00

W5 search batched (16 distinct dataset queries per request) parity

ef=128 · closed-loop · collection=bench2 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,5423,441parity
recall@100.96670.9692~equal
client p50288.12 ms295.78 ms1.03x
client p99294.42 ms339.82 ms1.15x
client p99.9303.98 ms402.78 ms1.33x
server p50287.48 ms294.25 ms1.02x
server p99293.67 ms325.77 ms1.11x
wall clock14.1 s14.5 s1.03x
queries sent50,00050,000
cpu99.7 s115.8 s1.16x
cpu, % of wall706%796%
waiting for a core9.7 ms86,320.1 ms8,933.52x
migrations01,552
faults min/maj752 / 022,143 / 0
peak RSS7.9 GiB22.6 GiB2.87x
disk written00
disk read00
per-batch latency (16 queries/request); queries: dataset, random-sample within the ±5.9% band this dataset's noise floor puts on W5: no measured difference, not a small one 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=990,000
metricstrawmANNQdrant
wall clock155.1 s241.5 s1.56x
of which upload5.8 s50.8 s8.73x
of which index wait144.5 s188.4 s1.30x
time to Green144.5 s188.4 s1.30x
cpu1,106.8 s1,048.0 s0.95x
cpu, % of wall714%434%
waiting for a core467.4 ms65,433.9 ms140.00x
migrations030,253
faults min/maj2,205,991 / 02,981,965 / 1,686,609
peak RSS17.4 GiB32.4 GiB1.86x
disk written5.7 GiB34.4 GiB
disk read0225.8 MiB

W6 quantized: scalar 1.13x

ef=128 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second8,1127,1601.13x
recall@100.96660.9676~equal
client p507.90 ms8.80 ms1.11x
client p998.72 ms13.85 ms1.59x
client p99.926.73 ms24.76 ms0.93x
server p507.79 ms8.45 ms1.09x
server p998.60 ms12.95 ms1.51x
wall clock6.2 s7.0 s1.13x
queries sent50,00050,000
cpu44.9 s55.0 s1.23x
cpu, % of wall723%784%
waiting for a core6.8 ms15,840.5 ms2,344.63x
migrations02,607
faults min/maj18 / 02,779 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00

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

ef=32 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=3.2 · rescore=true
metricstrawmANNQdrant
queries/second24,80817,1551.45x
recall@100.89160.8882~equal
client p502.57 ms3.54 ms1.38x
client p992.87 ms7.42 ms2.59x
client p99.922.28 ms24.74 ms1.11x
server p502.46 ms2.93 ms1.19x
server p992.75 ms5.90 ms2.15x
wall clock2.1 s3.0 s1.44x
queries sent50,00050,000
cpu15.5 s22.2 s1.43x
cpu, % of wall753%750%
waiting for a core1.6 ms12,726.4 ms7,863.76x
migrations05,947
faults min/maj6 / 0438 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00

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

ef=64 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=6.4 · rescore=true
metricstrawmANNQdrant
queries/second14,49611,5921.25x
recall@100.93950.9396~equal
client p504.42 ms5.32 ms1.20x
client p994.89 ms9.83 ms2.01x
client p99.919.24 ms23.49 ms1.22x
server p504.32 ms4.84 ms1.12x
server p994.77 ms8.40 ms1.76x
wall clock3.5 s4.4 s1.25x
queries sent50,00050,000
cpu25.8 s33.7 s1.31x
cpu, % of wall737%772%
waiting for a core2.0 ms14,418.4 ms7,077.00x
migrations04,624
faults min/maj0 / 0205 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00

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

ef=128 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second8,1207,2091.13x
recall@100.96660.9676~equal
client p507.90 ms8.76 ms1.11x
client p998.71 ms13.74 ms1.58x
client p99.924.79 ms23.13 ms0.93x
server p507.79 ms8.37 ms1.07x
server p998.60 ms12.68 ms1.48x
wall clock6.2 s7.0 s1.13x
queries sent50,00050,000
cpu44.9 s55.1 s1.23x
cpu, % of wall725%790%
waiting for a core2.7 ms15,464.4 ms5,828.97x
migrations02,507
faults min/maj0 / 0721 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00

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

ef=256 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=25.6 · rescore=true
metricstrawmANNQdrant
queries/second4,4854,2511.06x
recall@100.98080.9818~equal
client p5014.29 ms15.00 ms1.05x
client p9915.84 ms17.98 ms1.14x
client p99.923.82 ms29.11 ms1.22x
server p5014.18 ms14.63 ms1.03x
server p9915.69 ms17.52 ms1.12x
wall clock11.2 s11.8 s1.06x
queries sent50,00050,000
cpu80.0 s93.9 s1.17x
cpu, % of wall715%796%
waiting for a core7.6 ms18,336.9 ms2,428.09x
migrations0482
faults min/maj50 / 01,416 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00

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

ef=512 · closed-loop · collection=bench6 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=51.2 · rescore=true
metricstrawmANNQdrant
queries/second2,4572,411parity
recall@100.98930.9898~equal
client p5026.07 ms26.50 ms~equal
client p9928.96 ms30.34 ms1.05x
client p99.929.95 ms41.10 ms1.37x
server p5025.96 ms25.99 ms~equal
server p9928.81 ms29.90 ms1.04x
wall clock20.4 s20.8 s~equal
queries sent50,00050,000
cpu144.6 s165.7 s1.15x
cpu, % of wall709%797%
waiting for a core8.1 ms27,282.8 ms3,386.46x
migrations0424
faults min/maj5 / 02,482 / 0
peak RSS17.4 GiB32.4 GiB1.86x
disk written00
disk read00
within the ±3.1% band this dataset's noise floor puts on W6-ef512: no measured difference, not a small one

W7-upload binary quantization: load

upload · collection=bench7 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock59.3 s368.6 s6.21x
of which upload6.0 s178.8 s29.96x
of which index wait50.1 s171.5 s3.42x
time to Green50.1 s171.5 s3.42x
cpu288.9 s608.6 s2.11x
cpu, % of wall487%165%
waiting for a core148.7 ms39,248.8 ms263.93x
migrations127,92427,924.00x
faults min/maj1,698,301 / 02,997,835 / 1,861,540
peak RSS24.1 GiB41.0 GiB1.70x
disk written5.7 GiB37.2 GiB
disk read12.0 KiB317.9 MiB

W7 quantized: binary + oversampling 1.72x

ef=128 · closed-loop · collection=bench7 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second23,26413,5581.72x
recall@100.94180.9459~equal
client p502.72 ms4.16 ms1.53x
client p992.94 ms13.00 ms4.42x
client p99.918.45 ms20.16 ms1.09x
server p502.62 ms2.55 ms0.97x
server p992.83 ms9.87 ms3.49x
wall clock2.2 s3.7 s1.70x
queries sent50,00050,000
cpu16.2 s28.6 s1.76x
cpu, % of wall741%767%
waiting for a core1.5 ms93,182.8 ms61,915.16x
migrations019,523
faults min/maj45 / 04,456 / 0
peak RSS24.1 GiB41.0 GiB1.70x
disk written00
disk read00

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

upload · collection=bench7b2 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock77.0 s175.4 s2.28x
of which upload5.9 s39.4 s6.71x
of which index wait68.2 s134.3 s1.97x
time to Green68.2 s134.3 s1.97x
cpu312.3 s636.3 s2.04x
cpu, % of wall406%363%
waiting for a core170.2 ms44,457.0 ms261.27x
migrations329,7499,916.33x
faults min/maj1,756,298 / 112,162,663 / 1,824,782
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB30.3 GiB
disk read380.0 KiB218.6 MiB

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

ef=128 · closed-loop · collection=bench7b2 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second20,45912,3141.66x
recall@100.96130.9646~equal
client p503.11 ms4.61 ms1.49x
client p993.35 ms13.92 ms4.15x
client p99.914.11 ms26.40 ms1.87x
server p503.01 ms3.05 ms~equal
server p993.24 ms10.37 ms3.20x
wall clock2.5 s4.1 s1.65x
queries sent50,00050,000
cpu18.4 s31.4 s1.71x
cpu, % of wall740%766%
waiting for a core2.3 ms93,687.6 ms40,046.37x
migrations019,425
faults min/maj0 / 03,632 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

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=990,000
metricstrawmANNQdrant
wall clock75.0 s255.5 s3.41x
of which upload5.9 s88.9 s15.02x
of which index wait66.2 s205.5 s3.11x
time to Green66.2 s205.5 s3.11x
cpu298.1 s627.1 s2.10x
cpu, % of wall397%245%
waiting for a core143.3 ms46,578.9 ms324.94x
migrations627,6654,610.83x
faults min/maj1,736,859 / 22,437,715 / 1,816,141
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB32.9 GiB
disk read344.0 KiB262.7 MiB

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

ef=128 · closed-loop · collection=bench7b15 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second21,07712,6851.66x
recall@100.95790.9599~equal
client p503.00 ms4.48 ms1.49x
client p993.24 ms13.51 ms4.17x
client p99.925.79 ms23.95 ms0.93x
server p502.91 ms2.91 ms~equal
server p993.13 ms10.08 ms3.22x
wall clock2.4 s4.0 s1.65x
queries sent50,00050,000
cpu17.8 s30.6 s1.72x
cpu, % of wall736%768%
waiting for a core2.0 ms93,526.9 ms46,718.83x
migrations019,700
faults min/maj0 / 02,705 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

W8-upload PQ: load

upload · collection=bench8 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock386.1 s917.1 s2.38x
of which upload6.1 s28.4 s4.68x
of which index wait375.3 s886.3 s2.36x
time to Green375.3 s886.3 s2.36x
cpu2,968.7 s5,981.8 s2.01x
cpu, % of wall769%652%
waiting for a core1,353.4 ms27,983.8 ms20.68x
migrations0100,504
faults min/maj1,859,672 / 01,707,263 / 1,611,187
peak RSS30.2 GiB43.6 GiB1.45x
disk written5.7 GiB25.3 GiB
disk read92.0 KiB175.9 MiB

W8 quantized: PQ 1.21x

ef=128 · closed-loop · collection=bench8 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second6,1155,0671.21x
recall@100.96500.9659~equal
client p5010.44 ms12.55 ms1.20x
client p9911.27 ms15.65 ms1.39x
client p99.926.49 ms24.60 ms0.93x
server p5010.34 ms12.21 ms1.18x
server p9911.15 ms15.00 ms1.34x
wall clock8.3 s9.9 s1.20x
queries sent50,00050,000
cpu58.8 s78.7 s1.34x
cpu, % of wall713%794%
waiting for a core3.4 ms15,653.6 ms4,626.48x
migrations0650
faults min/maj0 / 03,577 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00

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

upload · collection=bench14t1 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock268.7 s177.0 s0.66x
of which upload5.8 s59.8 s10.28x
of which index wait259.9 s115.3 s0.44x
time to Green259.9 s115.3 s0.44x
cpu2,059.2 s650.8 s0.32x
cpu, % of wall766%368%
waiting for a core1,109.5 ms54,863.8 ms49.45x
migrations135,23035,230.00x
faults min/maj1,708,495 / 12,151,305 / 1,777,602
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB30.2 GiB
disk read40.0 KiB233.0 MiB

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

ef=128 · closed-loop · collection=bench14t1 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second14,06312,6051.12x
recall@100.96420.9557~equal
client p504.53 ms4.48 ms~equal
client p994.92 ms14.03 ms2.85x
client p99.915.31 ms25.03 ms1.63x
server p504.44 ms3.00 ms0.68x
server p994.81 ms10.63 ms2.21x
wall clock3.6 s4.0 s1.11x
queries sent50,00050,000
cpu26.2 s30.8 s1.17x
cpu, % of wall730%769%
waiting for a core2.0 ms94,570.4 ms46,769.80x
migrations018,635
faults min/maj0 / 05,125 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

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

upload · collection=bench14t15 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock271.8 s239.6 s0.88x
of which upload5.8 s61.9 s10.59x
of which index wait262.9 s159.4 s0.61x
time to Green262.9 s159.4 s0.61x
cpu2,082.3 s849.4 s0.41x
cpu, % of wall766%354%
waiting for a core1,126.5 ms53,287.1 ms47.31x
migrations129,53729,537.00x
faults min/maj1,739,075 / 02,294,444 / 1,803,171
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB30.9 GiB
disk read20.0 KiB235.1 MiB

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

ef=128 · closed-loop · collection=bench14t15 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second11,4939,9441.16x
recall@100.96480.9577~equal
client p505.55 ms5.88 ms1.06x
client p996.03 ms16.09 ms2.67x
client p99.919.45 ms24.04 ms1.24x
server p505.45 ms4.68 ms0.86x
server p995.92 ms12.53 ms2.12x
wall clock4.4 s5.1 s1.15x
queries sent50,00050,000
cpu31.9 s39.1 s1.23x
cpu, % of wall726%771%
waiting for a core2.9 ms97,130.4 ms33,761.35x
migrations017,066
faults min/maj0 / 06,949 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

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

upload · collection=bench14t2 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock269.6 s253.9 s0.94x
of which upload5.9 s77.2 s13.14x
of which index wait260.9 s177.4 s0.68x
time to Green260.9 s177.4 s0.68x
cpu2,059.1 s989.6 s0.48x
cpu, % of wall764%390%
waiting for a core1,112.1 ms72,137.4 ms64.87x
migrations033,208
faults min/maj1,772,660 / 02,223,495 / 1,827,480
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB30.7 GiB
disk read332.0 KiB213.0 MiB

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

ef=128 · closed-loop · collection=bench14t2 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second15,83211,5331.37x
recall@100.96630.9624~equal
client p504.02 ms4.93 ms1.23x
client p994.34 ms14.78 ms3.41x
client p99.919.09 ms29.95 ms1.57x
server p503.92 ms3.55 ms0.90x
server p994.23 ms11.15 ms2.64x
wall clock3.2 s4.4 s1.37x
queries sent50,00050,000
cpu23.5 s33.6 s1.43x
cpu, % of wall734%767%
waiting for a core2.5 ms94,664.6 ms37,682.99x
migrations019,444
faults min/maj0 / 04,576 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

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

upload · collection=bench14t4 · client -p 2 -t 2 -c 1 (-p, -t, -c bfb default) · n=990,000
metricstrawmANNQdrant
wall clock271.7 s321.0 s1.18x
of which upload5.9 s114.2 s19.47x
of which index wait262.9 s204.5 s0.78x
time to Green262.9 s204.5 s0.78x
cpu2,071.0 s1,050.4 s0.51x
cpu, % of wall762%327%
waiting for a core1,135.9 ms62,528.4 ms55.05x
migrations133,56633,566.00x
faults min/maj1,900,954 / 22,695,357 / 1,919,687
peak RSS36.2 GiB43.6 GiB1.20x
disk written5.7 GiB32.1 GiB
disk read24.0 KiB216.3 MiB

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

ef=128 · closed-loop · collection=bench14t4 · client -p 64 -t 16 -c 2 · n=50,000 · oversampling=12.8 · rescore=true
metricstrawmANNQdrant
queries/second12,93710,0061.29x
recall@100.96720.9680~equal
client p504.92 ms5.79 ms1.18x
client p995.37 ms16.51 ms3.07x
client p99.927.84 ms26.39 ms0.95x
server p504.82 ms4.56 ms0.95x
server p995.27 ms12.56 ms2.38x
wall clock3.9 s5.0 s1.29x
queries sent50,00050,000
cpu28.4 s38.9 s1.37x
cpu, % of wall728%772%
waiting for a core2.2 ms97,214.2 ms44,450.37x
migrations016,353
faults min/maj0 / 04,632 / 0
peak RSS36.2 GiB43.6 GiB1.20x
disk written00
disk read00

W9 exact / brute force 1.27x

exact · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=2,000
metricstrawmANNQdrant
queries/second13101.27x
client p50620.80 ms810.76 ms1.31x
client p99825.19 ms848.33 ms1.03x
client p99.9836.42 ms878.97 ms1.05x
server p50620.05 ms809.32 ms1.31x
server p99824.50 ms846.86 ms1.03x
wall clock159.0 s202.1 s1.27x
queries sent2,0002,000
cpu636.2 s1,612.5 s2.53x
cpu, % of wall400%798%
waiting for a core71.2 ms14,216.7 ms199.53x
migrations06,641
faults min/maj0 / 01,513 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00
1.27x is 2.53x less work per query x 0.50x cores busy during the row (4.00 against 7.98) x 1.00x clock: the middle term is occupancy, not search speed brute force over the whole collection, no index involved

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

ef=32 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second10,0767,3431.37x
recall@100.89280.8936~equal
client p50783 µs1.01 ms1.29x
client p991.26 ms2.00 ms1.58x
client p99.91.57 ms2.53 ms1.61x
server p50682 µs818 µs1.20x
server p991.16 ms1.73 ms1.49x
wall clock5.0 s6.8 s1.37x
queries sent50,00050,000
cpu34.7 s40.3 s1.16x
cpu, % of wall694%589%
waiting for a core4.0 ms14,951.6 ms3,779.75x
migrations084,216
faults min/maj0 / 01,035 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00

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

ef=64 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second6,0824,7901.27x
recall@100.94000.9434~equal
client p501.31 ms1.56 ms1.19x
client p992.03 ms3.09 ms1.52x
client p99.92.48 ms3.86 ms1.56x
server p501.21 ms1.33 ms1.10x
server p991.92 ms2.73 ms1.42x
wall clock8.3 s10.5 s1.27x
queries sent50,00050,000
cpu58.1 s66.3 s1.14x
cpu, % of wall704%633%
waiting for a core5.9 ms41,212.9 ms7,024.29x
migrations0157,577
faults min/maj0 / 0535 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00

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

ef=128 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second3,5813,0621.17x
recall@100.96670.9692~equal
client p502.23 ms2.54 ms1.14x
client p993.47 ms4.62 ms1.33x
client p99.93.89 ms5.73 ms1.47x
server p502.12 ms2.28 ms1.08x
server p993.36 ms4.25 ms1.26x
wall clock14.0 s16.4 s1.17x
queries sent50,00050,000
cpu98.9 s108.4 s1.10x
cpu, % of wall706%662%
waiting for a core9.6 ms57,485.6 ms6,004.56x
migrations0177,203
faults min/maj0 / 0472 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00

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

ef=256 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second2,0581,8111.14x
recall@100.98110.9822~equal
client p503.88 ms4.32 ms1.11x
client p996.13 ms7.57 ms1.24x
client p99.96.98 ms9.01 ms1.29x
server p503.76 ms4.00 ms1.06x
server p996.01 ms7.11 ms1.18x
wall clock24.3 s27.6 s1.14x
queries sent50,00050,000
cpu171.9 s190.4 s1.11x
cpu, % of wall706%689%
waiting for a core17.3 ms83,088.3 ms4,804.97x
migrations0196,685
faults min/maj0 / 0904 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00

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

ef=512 · closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=50,000
metricstrawmANNQdrant
queries/second1,1701,051parity
recall@100.98940.9900~equal
client p506.79 ms7.53 ms1.11x
client p9910.95 ms12.35 ms1.13x
client p99.912.34 ms14.29 ms1.16x
server p506.67 ms7.09 ms1.06x
server p9910.82 ms11.75 ms1.09x
wall clock42.8 s47.6 s1.11x
queries sent50,00050,000
cpu301.4 s338.6 s1.12x
cpu, % of wall704%711%
waiting for a core24.7 ms92,337.9 ms3,739.12x
migrations0146,149
faults min/maj0 / 02,196 / 0
peak RSS30.2 GiB43.6 GiB1.45x
disk written00
disk read00
within the ±11.6% band this dataset's noise floor puts on W10-ef512: no measured difference, not a small one

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 clock48.8 s83.0 s1.70x
of which upload1.6 s6.7 s4.20x
of which index wait39.1 s74.2 s1.90x
time to Green39.1 s74.2 s1.90x
cpu299.7 s473.9 s1.58x
cpu, % of wall614%571%
waiting for a core181.1 ms17,205.5 ms95.00x
migrations06,853
faults min/maj453,100 / 41346,436 / 446,599
peak RSS34.6 GiB43.6 GiB1.26x
disk written1.1 GiB5.3 GiB
disk read768.0 KiB53.5 MiB

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

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9581,3952.84x
recall@101.00000.9995~equal
client p5016.08 ms45.57 ms2.83x
client p9917.90 ms50.14 ms2.80x
client p99.926.35 ms58.15 ms2.21x
server p5015.94 ms44.95 ms2.82x
server p9917.69 ms49.62 ms2.81x
wall clock12.7 s35.9 s2.83x
queries sent50,00050,000
cpu90.0 s286.5 s3.18x
cpu, % of wall710%799%
waiting for a core6.6 ms39,910.4 ms6,010.56x
migrations0471
faults min/maj48 / 04,266 / 0
peak RSS34.6 GiB43.6 GiB1.26x
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-sel10 filtered search, any of 10 keywords (~10% of bench12) 3.04x

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second2,5368353.04x
recall@100.98930.9972~equal
client p5025.30 ms76.84 ms3.04x
client p9927.51 ms84.25 ms3.06x
client p99.932.76 ms98.42 ms3.00x
server p5025.19 ms75.96 ms3.02x
server p9927.26 ms83.84 ms3.08x
wall clock19.8 s59.9 s3.03x
queries sent50,00050,000
cpu139.8 s478.6 s3.42x
cpu, % of wall708%798%
waiting for a core8.3 ms57,403.3 ms6,914.33x
migrations01,105
faults min/maj6 / 26,255 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read12.0 KiB0
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)

ef=32 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9593,802-
recall@101.00000.9829
client p5016.09 ms16.52 ms
client p9917.88 ms30.08 ms
client p99.930.97 ms44.02 ms
server p5015.94 ms16.12 ms
server p9917.68 ms25.77 ms
wall clock12.7 s13.2 s
queries sent50,00050,000
cpu89.8 s104.7 s
cpu, % of wall709%793%
waiting for a core7.2 ms68,961.4 ms
migrations02,672
faults min/maj0 / 019,528 / 0
peak RSS34.6 GiB43.6 GiB
disk written00
disk read00
recall unequal: 1.0000 vs 0.9829; §7.4 compares at equal recall

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

ef=64 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9582,3291.70x
recall@101.00000.9968~equal
client p5016.10 ms27.30 ms1.70x
client p9917.85 ms30.88 ms1.73x
client p99.923.13 ms38.66 ms1.67x
server p5015.98 ms26.92 ms1.68x
server p9917.66 ms30.28 ms1.71x
wall clock12.7 s21.5 s1.70x
queries sent50,00050,000
cpu90.1 s171.6 s1.90x
cpu, % of wall710%798%
waiting for a core6.1 ms27,271.3 ms4,442.49x
migrations0303
faults min/maj0 / 02,525 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

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

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9411,3982.82x
recall@101.00000.9995~equal
client p5016.10 ms45.80 ms2.84x
client p9917.86 ms49.57 ms2.78x
client p99.952.45 ms56.59 ms1.08x
server p5015.96 ms45.02 ms2.82x
server p9917.67 ms48.95 ms2.77x
wall clock12.7 s35.8 s2.81x
queries sent50,00050,000
cpu90.0 s285.9 s3.18x
cpu, % of wall707%798%
waiting for a core6.1 ms39,808.4 ms6,481.60x
migrations0550
faults min/maj13 / 103,145 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read88.0 KiB0

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

ef=256 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9668574.63x
recall@101.00000.9999~equal
client p5016.08 ms74.30 ms4.62x
client p9917.93 ms80.77 ms4.50x
client p99.937.02 ms88.55 ms2.39x
server p5015.95 ms73.85 ms4.63x
server p9917.72 ms79.83 ms4.51x
wall clock12.7 s58.4 s4.61x
queries sent50,00050,000
cpu89.9 s466.5 s5.19x
cpu, % of wall709%799%
waiting for a core6.2 ms54,864.6 ms8,851.00x
migrations01,177
faults min/maj54 / 06,221 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

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

ef=512 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second3,9565527.16x
recall@101.00001.0000~equal
client p5016.13 ms115.60 ms7.17x
client p9917.84 ms124.34 ms6.97x
client p99.930.91 ms134.45 ms4.35x
server p5015.98 ms114.90 ms7.19x
server p9917.66 ms123.81 ms7.01x
wall clock12.7 s90.6 s7.14x
queries sent50,00050,000
cpu90.2 s723.8 s8.03x
cpu, % of wall711%799%
waiting for a core5.4 ms68,963.1 ms12,822.75x
migrations02,374
faults min/maj0 / 08,405 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

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/second7,4812,160-
recall@100.93780.9699
client p508.51 ms29.69 ms
client p999.45 ms32.99 ms
client p99.920.99 ms43.04 ms
server p508.41 ms29.05 ms
server p999.29 ms32.60 ms
wall clock6.7 s23.2 s
queries sent50,00050,000
cpu48.2 s185.2 s
cpu, % of wall717%799%
waiting for a core2.3 ms29,128.7 ms
migrations0303
faults min/maj0 / 03,330 / 0
peak RSS34.6 GiB43.6 GiB
disk written00
disk read00
recall unequal: 0.9378 vs 0.9699; §7.4 compares at equal recall

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

ef=64 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4,4331,354-
recall@100.97280.9901
client p5014.46 ms47.13 ms
client p9915.77 ms52.55 ms
client p99.929.24 ms64.03 ms
server p5014.35 ms46.77 ms
server p9915.62 ms51.90 ms
wall clock11.3 s37.0 s
queries sent50,00050,000
cpu80.7 s294.3 s
cpu, % of wall713%796%
waiting for a core3.7 ms41,081.1 ms
migrations0545
faults min/maj0 / 04,735 / 0
peak RSS34.6 GiB43.6 GiB
disk written00
disk read00
recall unequal: 0.9728 vs 0.9901; §7.4 compares at equal recall

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

ef=128 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second2,5178323.03x
recall@100.98930.9972~equal
client p5025.52 ms76.99 ms3.02x
client p9927.65 ms84.22 ms3.05x
client p99.928.54 ms92.99 ms3.26x
server p5025.41 ms76.18 ms3.00x
server p9927.52 ms83.78 ms3.04x
wall clock19.9 s60.2 s3.02x
queries sent50,00050,000
cpu141.0 s479.6 s3.40x
cpu, % of wall708%797%
waiting for a core5.0 ms57,549.0 ms11,424.40x
migrations01,042
faults min/maj0 / 05,123 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

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

ef=256 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second1,4685222.81x
recall@100.99590.9993~equal
client p5043.72 ms122.27 ms2.80x
client p9947.08 ms133.88 ms2.84x
client p99.948.66 ms143.82 ms2.96x
server p5043.60 ms121.76 ms2.79x
server p9946.93 ms132.97 ms2.83x
wall clock34.1 s95.7 s2.81x
queries sent50,00050,000
cpu240.2 s765.9 s3.19x
cpu, % of wall704%800%
waiting for a core11.3 ms74,054.5 ms6,565.53x
migrations02,862
faults min/maj3 / 010,499 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

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

ef=512 · closed-loop · collection=bench12 · client -p 64 -t 16 -c 2 · n=50,000
metricstrawmANNQdrant
queries/second4433381.31x
recall@101.00000.9998~equal
client p50147.64 ms189.02 ms1.28x
client p99160.17 ms205.24 ms1.28x
client p99.9163.18 ms225.01 ms1.38x
server p50147.26 ms188.12 ms1.28x
server p99159.79 ms204.73 ms1.28x
wall clock112.8 s148.0 s1.31x
queries sent50,00050,000
cpu796.9 s1,183.0 s1.48x
cpu, % of wall706%799%
waiting for a core70.1 ms87,860.9 ms1,253.53x
migrations05,854
faults min/maj0 / 015,545 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00

W13 scroll / pagination 1.09x

closed-loop · collection=bench2 · client -p 8 -t 2 -c 1 (-t, -c bfb default) · n=200,000
metricstrawmANNQdrant
queries/second50,41146,3141.09x
client p50139 µs159 µs1.15x
client p99233 µs292 µs1.25x
client p99.9271 µs446 µs1.64x
server p5011 µs28 µs2.57x
server p9916 µs89 µs5.58x
wall clock4.1 s2.2 s0.54x
queries sent200,000100,000
cpu5.6 s9.2 s1.63x
cpu, % of wall137%411%
waiting for a core4.6 ms812.8 ms176.61x
migrations0113,205
faults min/maj0 / 0677 / 0
peak RSS34.6 GiB43.6 GiB1.26x
disk written00
disk read00
strawmANN: -n 200000 (4x the table's 50000) Qdrant: -n 100000 (2x the table's 50000) strawmANN: 0.13 ms of the client's 0.14 ms p50 is not server time (13x), so 92% of this row is the load generator and the socket Qdrant: 0.13 ms of the client's 0.16 ms p50 is not server time (6x), so 82% of this row is the load generator and the socket 1.09x is 3.26x less work per query x 0.33x cores busy during the row (1.38 against 4.21) x 1.00x clock x 1.02x counted on-CPU share: the middle term is occupancy, not search speed

W11-steady mixed read/write below the rebuild threshold: search bench2 while 49,500 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/second541494-
client p5013.96 ms12.14 ms
client p9940.01 ms68.87 ms
client p99.9153.28 ms87.99 ms
server p5012.87 ms11.29 ms
server p9939.02 ms67.79 ms
wall clock32.7 s32.7 s
queries sent16,48014,203
cpu256.2 s252.7 s
cpu, % of wall784%773%
waiting for a core195,850.3 ms212,991.1 ms
migrations77944,937
faults min/maj485,661 / 15,720652,509 / 127,904
peak RSS36.2 GiB43.6 GiB
disk written290.1 MiB12.2 GiB
disk read64.4 MiB73.6 MiB
strawmANN: qps over the 26.1 s of the append the search saw (505 over the whole search); append 1,900 points/s Qdrant: qps over the 26.1 s of the append the search saw (427 over the whole search); append 1,900 points/s strawmANN pass 1 +15% against two passes that agree: one pass set the spread on this row, so a band built from it is not a noise band search-during-write; no recall join

W11 mixed read/write: search bench2 while 198,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/second12172-
client p5058.76 ms115.38 ms
client p99196.61 ms230.21 ms
client p99.9225.00 ms371.97 ms
server p5057.49 ms113.96 ms
server p99194.82 ms228.68 ms
wall clock75.2 s187.5 s
queries sent8,00612,040
cpu603.3 s1,488.1 s
cpu, % of wall802%794%
waiting for a core506,643.3 ms1,211,680.4 ms
migrations1,01137,046
faults min/maj769,326 / 1,1331,053,039 / 352,436
peak RSS36.2 GiB43.6 GiB
disk written1.1 GiB9.8 GiB
disk read7.5 MiB167.0 MiB
strawmANN: qps over the 60.0 s of the append the search saw (106 over the whole search); append 3,300 points/s Qdrant: qps over the 186.7 s of the append the search saw (68 over the whole search); append 1,322 points/s strawmANN -11% across its passes, monotonically: the spread on this row is drift rather than noise, so the median is a trend's midpoint and not a repeatable measurement 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(7%)
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(6%)
okmachine is quiescent: 0.10 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/dbpedia-openai-1m/base.fbin --queries $DATA/dbpedia-openai-1m/queries.fbin \
  --ground-truth $DATA/dbpedia-openai-1m/gt/dbpedia-openai-1m.cosine.k100.gt.json --metric cosine \
  --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/dbpedia-openai-1m/base.fbin --queries $DATA/dbpedia-openai-1m/queries.fbin \
  --ground-truth $DATA/dbpedia-openai-1m/gt/dbpedia-openai-1m.cosine.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.