GenericVectorBuilder

Benchmark

Summary and all runs

Vector engine benchmark: eshoponweb

Run started 5 Oct 2026, 08:54 UTC. Data: eShopOnWeb, 524 vectors. Queries: 20 labelled questions.

Used by: published-2026-10-08 (basis v6)

The runs of v6 were also used by the set blocked-2026-10-05-v6, which was not published; its verdict, design/verdicts/v6-verdict.md, holds the word BLOCK.

sources
  • file design/verdicts/v6-verdict.md#BLOCK = BLOCK
  • consolidated consolidated:reuse[session=v6].verdict = design/verdicts/v6-verdict.md
  • consolidated consolidated:reuse[session=v6].blockedFolders[0] = blocked-2026-10-05-v6

Machine: CPU Intel(R) Xeon(R) CPU E5-1620 v3 @ 3.50GHz; Logical CPUs 8; RAM (GiB) 62.7; OS Ubuntu 24.04.5 LTS, kernel 6.8.0-142-generic; Governor performance; Partition client 0-1,4-5; engines 2-3,6-7; Release build; Exact mode seconds 60.

Warm-up, as this run's notes record it: Warm-up and settle check, untimed, right before every timed pass: the pass's own search at the pass's own number of searchers for at least 15 s and at least 20 searches (at most 120 s), read in windows of at least 2 s and 100 searches; then a 3 s trial of the same pass.

No CPU clock pin is recorded in this run's notes.

Enginep50 (ms)Searches per second, one searcherSearches per second, eight searchers at onceExact mode p50 (ms)Client CPU per search, one searcher (ms)Recall in hitsFlags
Chroma2.03486807-0.45200 of 200
ClickHouse4.512154936.100.82199 of 200Un
DuckDB3.522815993.994.84200 of 200
Elasticsearch1.317512,7131.250.46200 of 200Ix
MariaDB0.621,5825,9401.580.49199 of 200
Milvus2.224301,282-0.55200 of 200
MongoDB Atlas Local1.416942,0881.250.31200 of 200
OpenSearch2.004941,5122.560.46200 of 200
Oracle 23ai Free0.901,0892,8972.380.87200 of 200Un
Qdrant (HNSW)0.921,0753,4540.900.73200 of 200
Qdrant (exact)0.881,1223,291-0.74200 of 200
Redis
redis holds its data in memory: its saved docs page says 'Redis is an in-memory but persistent on disk database', and its compose file sets save "300 1" and appendonly no.
sources
  • doc doc:design/engine-docs/redis-faq-2026-10-07.html#Redis is an in-memory but persistent on disk database = Redis is an in-memory but persistent on disk database
  • file deploy/engines/redis.compose.yaml#--save "300 1" = --save "300 1"
  • file deploy/engines/redis.compose.yaml#--appendonly no = --appendonly no
0.372,6205,1330.350.55200 of 200Un
SQL Server 20253.82256614-1.18200 of 200
SQL Server 2025 + DiskANN3.562766913.561.00193 of 200
Typesense4.042445915.480.50200 of 200
Vespa1.865231,5601.850.94200 of 200
Weaviate5.18172312-0.57200 of 200
pgvector0.821,2004,1422.170.66200 of 200
sqlite-vec1.855301,1511.851.97200 of 200

Engines are listed in alphabetical order. The table does not rank them.

A dash means the table has no figure there.

The small markers after an engine name are flags. Hover a marker for its evidence, or read the list below the tables.

  • Un unsettled-target The engine did not pass its own settle check before a timed pass. The evidence names the check.
  • Ix index-not-ready The engine did not report a finished index after the load or after the searches.
Evidence behind the flags
  • ClickHouse unsettled-target latency had NOT settled when timing began for default@8 (each by its own warm-up at its own concurrency and a trial of the same pass within 10% of the warm-up's settled figure). default@8: warm-up 15.0 s and 7,401 searches (0 failed) at 8 searchers; QPS of the last windows 458, 442, 444 (windows of at least 2 s and 100 searches); trial of 1,581 searches in 3.0 s at 8 searchers: 525 QPS against the settled 444 QPS, 16% apart (limit 10%), so the warm-up was EXTENDED once (30.0 s and 14,706 searches (0 failed) at 8 searchers; QPS of the last windows 530, 525, 452 (windows of at least 2 s and 100 searches), its last 3 windows differed by more than 5%); second trial of 1,311 searches in 3.0 s at 8 searchers: 435 QPS against the settled 525 QPS, 21% apart (limit 10%); still disagreeing after the extension; exact: warm-up 15.0 s and 2,370 searches (0 failed) at 1 searcher; p50 of the last windows 6.089, 6.058, 6.067 ms (windows of at least 2 s and 100 searches); trial of 487 searches in 3.0 s at 1 searcher: p50 6.077 ms against the settled p50 6.067 ms, 0% apart (limit 10%); default@1: warm-up 15.0 s and 3,267 searches (0 failed) at 1 searcher; p50 of the last windows 4.489, 4.504, 4.493 ms (windows of at least 2 s and 100 searches); trial of 657 searches in 3.0 s at 1 searcher: p50 4.468 ms against the settled p50 4.493 ms, 1% apart (limit 10%). Its numbers may still include warm-up; rerun before quoting them.
  • Elasticsearch index-not-ready afterLoad: the engine's index state read not ready, 0 of 524 vectors indexed
  • Elasticsearch index-not-ready afterSearch: the engine's index state read not ready, 0 of 524 vectors indexed
  • Oracle 23ai Free unsettled-target latency had NOT settled when timing began for default@1, default@8 (each by its own warm-up at its own concurrency and a trial of the same pass within 10% of the warm-up's settled figure). exact: warm-up 15.0 s and 5,949 searches (0 failed) at 1 searcher; p50 of the last windows 2.363, 2.376, 2.356 ms (windows of at least 2 s and 100 searches); trial of 1,229 searches in 3.0 s at 1 searcher: p50 2.387 ms against the settled p50 2.363 ms, 1% apart (limit 10%); default@1: warm-up 15.0 s and 16,397 searches (0 failed) at 1 searcher; p50 of the last windows 0.860, 0.892, 0.913 ms (windows of at least 2 s and 100 searches) (its last 3 windows differed by more than 5%); trial of 3,246 searches in 3.0 s at 1 searcher: p50 0.900 ms against the settled p50 0.892 ms, 1% apart (limit 10%), so the warm-up was EXTENDED once (30.0 s and 32,617 searches (0 failed) at 1 searcher; p50 of the last windows 0.883, 0.857, 0.926 ms (windows of at least 2 s and 100 searches), its last 3 windows differed by more than 5%); second trial of 3,341 searches in 3.0 s at 1 searcher: p50 0.874 ms against the settled p50 0.883 ms, 1% apart (limit 10%); still disagreeing after the extension; default@8: warm-up 15.0 s and 48,930 searches (0 failed) at 8 searchers; QPS of the last windows 3,514, 2,364, 3,100 (windows of at least 2 s and 100 searches) (its last 3 windows differed by more than 5%); trial of 7,829 searches in 3.1 s at 8 searchers: 2,519 QPS against the settled 3,100 QPS, 23% apart (limit 10%), so the warm-up was EXTENDED once (120.0 s and 315,148 searches (0 failed) at 8 searchers; QPS of the last windows 2,207, 2,452, 2,930 (windows of at least 2 s and 100 searches), the 120 s cap ran out); second trial of 7,269 searches in 3.3 s at 8 searchers: 2,230 QPS against the settled 2,452 QPS, 10% apart (limit 10%); still disagreeing after the extension. Its numbers may still include warm-up; rerun before quoting them.
  • Redis unsettled-target latency had NOT settled when timing began for default@8 (each by its own warm-up at its own concurrency and a trial of the same pass within 10% of the warm-up's settled figure). default@1: warm-up 15.0 s and 39,692 searches (0 failed) at 1 searcher; p50 of the last windows 0.352, 0.350, 0.369 ms (windows of at least 2 s and 100 searches) (its last 3 windows differed by more than 5%); trial of 8,035 searches in 3.0 s at 1 searcher: p50 0.355 ms against the settled p50 0.352 ms, 1% apart (limit 10%), so the warm-up was EXTENDED once (30.0 s and 77,908 searches (0 failed) at 1 searcher; p50 of the last windows 0.379, 0.384, 0.376 ms (windows of at least 2 s and 100 searches)); second trial of 7,691 searches in 3.0 s at 1 searcher: p50 0.388 ms against the settled p50 0.379 ms, 3% apart (limit 10%); settled after the extension; exact: warm-up 15.0 s and 41,325 searches (0 failed) at 1 searcher; p50 of the last windows 0.367, 0.376, 0.359 ms (windows of at least 2 s and 100 searches); trial of 8,543 searches in 3.0 s at 1 searcher: p50 0.342 ms against the settled p50 0.367 ms, 7% apart (limit 10%); default@8: warm-up 15.0 s and 75,695 searches (0 failed) at 8 searchers; QPS of the last windows 4,921, 5,016, 5,277 (windows of at least 2 s and 100 searches) (its last 3 windows differed by more than 5%); trial of 15,098 searches in 3.0 s at 8 searchers: 5,030 QPS against the settled 5,016 QPS, 0% apart (limit 10%), so the warm-up was EXTENDED once (30.0 s and 153,806 searches (0 failed) at 8 searchers; QPS of the last windows 5,068, 5,484, 4,940 (windows of at least 2 s and 100 searches), its last 3 windows differed by more than 5%); second trial of 15,130 searches in 3.0 s at 8 searchers: 5,041 QPS against the settled 5,068 QPS, 1% apart (limit 10%); still disagreeing after the extension. Its numbers may still include warm-up; rerun before quoting them.

Full results

This report is printed as the run wrote it, except for any sentence a note above it says was left out. This page does not check the engine texts in it. The summary page's facts table gives the label of each fact it uses.

Run 2026-10-05T08:54:48Z (run-all). Command line:

~/gvb-work/lanes/v6-final/src/GenericVectorBuilder.Bench/bin/Release/net10.0/GenericVectorBuilder.Bench.dll run-all --pipeline eshoponweb --queries golden --seed 602 --out ~/ForClaude/GenericVectorBuilder/bench-results
engineindexload rows/sp50 msp95 msp99 msQPS@1QPS@8client CPU ms/search@1client CPU ms/search@8recall@10nDCG@10RAMdisk
sqlexact VECTOR_DISTANCE cosine, no vector index (full scan)5753.824.355.69255.6613.91.181.181.0000.518530.8 MiB5.15 MiB
opensearchfaiss HNSW float32, no compression, m=16, ef_construction=128, cosinesimil; search k=top, ef_search=100; 1 shard, 0 replicas; graph built at any segment size (approximate_threshold=0); force-merged to one segment after the load4212.002.252.78494.11511.90.460.511.0000.5182.56 GiB9.55 MiB
pgvectorHNSW vector_cosine_ops m=16 ef_construction=128, hnsw.ef_search=100 per query, float32 vector(n), cosine; exact mode = same query with index scans off (sequential scan)6110.820.951.221200.44142.50.660.531.0000.518100.8 MiB7.58 MiB
duckdbHNSW (vss extension) FLOAT[n] metric=cosine m=16 ef_construction=128, ef_search=100 per connection, persistent (hnsw_enable_experimental_persistence=true, checkpoint_threshold=256MB); exact mode = array_cosine_similarity sequential scan; score = 1 - cosine distance; searches run concurrently, one connection per searcher (opened as searchers arrive, at most 32), writes run one at a time and never overlap a search1,5593.523.924.99280.9598.54.846.641.0000.518-2.9 MiB
milvusHNSW M=16 efConstruction=128, ef=100, metric COSINE, Strong consistency searches; approximate only (no exact mode)1,1752.222.743.65430.11281.50.550.631.0000.518203.6 MiB10.87 MiB
sqlitevecvec0 brute-force scan, no ANN index (exact), float32, cosine distance, default chunk_size=1024; score = 1 - cosine distance; searches run concurrently, one WAL reader connection per searcher (opened as searchers arrive, at most 32), writes run one at a time and may overlap searches4,6901.852.122.45529.81150.71.973.471.0000.518-9.72 MiB
qdrant-hnswHNSW m=16 ef_construct=100, hnsw_ef=server default, cosine; indexing_threshold_kb 1 and full_scan_threshold_kb 10 (server defaults are 10,000 each) so a small collection builds and walks its graph5,4460.921.031.381074.83453.80.730.521.0000.51839.84 MiB164.1 MiB
typesenseHNSW float32 (hnswlib), m=16, ef_construction=128, cosine; search k=top, ef=100; exact mode = filter ordinal:>=0 with flat_search_cutoff; index held in memory1,0404.044.385.02243.8590.90.500.561.0000.518114.2 MiB0 B
qdrantexact scan: the builder's sink sends exact=true on every search, so no HNSW graph is used whether or not Qdrant has built one (see the index state)8,5970.880.991.381122.03291.40.740.531.0000.51838.17 MiB196.08 MiB
oracleHNSW in-memory neighbor graph NEIGHBORS=16 EFCONSTRUCTION=128, EFSEARCH=100 per query, cosine; exact mode = FETCH EXACT FIRST (full scan); Oracle Free caps itself at 2 CPUs (cpu_count 2 in V$PARAMETER, edition FREE in V$INSTANCE, 8 host CPUs in V$OSSTAT NUM_CPUS; the 2 CPU thread limit is Oracle's documented Free edition limit)2,0070.901.061.791089.12896.50.870.641.0000.5182.17 GiB0 B
weaviateHNSW maxConnections(M)=16 efConstruction=128, ef=-1 (dynamic: limit x 8 clamped 100..500), cosine, no quantization; approximate only (no exact mode)9985.1810.411.3171.6312.10.570.601.0000.51870.7 MiB2.96 MiB
sql-diskannDiskANN (preview) via VECTOR_SEARCH, cosine, build {"StartId":"306", "L":"48", "M":"8", "R":"48"}; the exact mode scans the same table6373.564.065.51276.4690.71.001.090.9650.526529.7 MiB4.52 MiB
chromaHNSW M=16 ef_construction=128, ef_search=100 (Chroma default), cosine; approximate only (no exact mode)8602.032.332.54486.3806.90.450.461.0000.51846.11 MiB414.16 KiB
redisHNSW TYPE FLOAT32 M=16 EF_CONSTRUCTION=128, EF_RUNTIME=100 per query, cosine; exact mode = FLAT index built on first exact query11,4140.370.470.682620.45132.70.550.361.0000.51821.46 MiB2.43 MiB
vespaHNSW float32 tensor, prenormalized-angular (cosine), max-links-per-node=16, neighbors-to-explore-at-insert=128; search targetHits=top, ef=100 via exploreAdditionalHits; exact mode = approximate:false; vectors held in memory2881.862.262.53522.71560.00.940.881.0000.5182.77 GiB6.98 MiB
mariadbVECTOR INDEX (HNSW variant) DISTANCE=cosine, M=16 (no ef_construction setting exists), mhnsw_ef_search=100 per statement (the ef 100 most engines here use, so the search effort matches; MariaDB's own default is 20; recall@10 at ef 100 falls as the set grows (random 1024-dimension vectors, measured 2026-10-04: 0.99 at 524, 0.89 to 0.92 at 2,000; an earlier run gave about 0.09 at 100,000 [Correction 3])), mhnsw_max_cache_size 4G; exact mode = IGNORE INDEX full scan1,0200.620.700.851581.55940.10.490.380.9950.518170.6 MiB22.01 MiB
elasticsearchHNSW float32, no quantization, m=16, ef_construction=128, cosine; search k=top, num_candidates=100; 1 shard, 0 replicas; force-merged to one segment after the load (at 1,024 dimensions a segment under 1,043 vectors gets no graph)5431.311.491.73751.02713.20.460.501.0000.5182.6 GiB2.39 MiB
clickhousevector_similarity HNSW cosineDistance, quantization bf16, M=16 ef_construction=128, hnsw_candidate_list_size_for_search=256, rescoring off; exact mode = full scan with skip indexes off2,9774.515.756.75214.7492.80.821.020.9950.528199.5 MiB3.26 MiB
mongodbvectorSearch index, HNSW maxEdges=16 numEdgeCandidates=128, float32 binData, cosine, numCandidates=20x hits (min 100); exact mode = $vectorSearch exact:true2,9691.411.641.99693.72088.10.310.291.0000.518656.1 MiB42.39 KiB

Details per target

SQL Server 2025 sql
OpenSearch opensearch
pgvector
DuckDB duckdb
Milvus milvus
sqlite-vec sqlitevec
Qdrant (HNSW) qdrant-hnsw
Typesense typesense
Qdrant (exact) qdrant
Oracle 23ai Free oracle
Weaviate weaviate
SQL Server 2025 + DiskANN sql-diskann
Chroma chroma
Redis redis
Vespa vespa
MariaDB mariadb
Elasticsearch elasticsearch
ClickHouse clickhouse
MongoDB Atlas Local mongodb

Notes

Raw files

results.md is kept unedited. It still holds the sentences this page leaves out of its copy. Count: 2

The raw files below hold the recorded statements that the corrections above refer to, as written.