release · v0.2.0 · 7 complete · 1 partial · 0 valid negative / 21 lanes

Antfly Circus — v0.2.0

Benchmark results for Antfly v0.2.0. Measured lanes retain their own machine, completion time, runtime, and protocol; lanes without selected evidence remain visible.

Reading contract

Each selected outcome binds its Antfly evidence to v0.2.0. Machines, dates, and protocols may differ.

I

2 of 3 lanes measured

VectorDBBench

Qualified vector search quality, throughput, serial latency, serving demand, and database volume across operating points.

i

vector-vdbbench-50k

complete

50K

Reviewed 50K vector search quality, throughput, latency, serving demand, and valid database volume evidence.

Methodology scope · protocol · interpretation

VectorDBBench methodology

Antfly subject and execution lane

Circus accepts an explicit subject manifest containing the asserted release tag, commit, and Linux/arm64 Antfly binary. It records the binary path, SHA-256, architecture, and observed --version output, while treating the supplied tag and commit as release metadata. The honed matrix mounts that binary read-only into Antfly’s Linux container. Every comparison engine runs in the same private Docker network; no native macOS database is mixed into this benchmark.

The public benchmarks/VectorDBBench checkout remains clean. Circus-owned parameter selection, compatibility fixes, query partitioning, and diagnostics live in benchmarks/VectorDBBench-harness and are loaded as a runtime overlay.

Workloads and query protocol

The publication matrix contains six engines on both upstream workloads:

  • Performance1536D50K: 50,000 vectors with 1,536 dimensions.
  • Performance768D1M: 1,000,000 vectors with 768 dimensions.

For each workload, the 1,000 upstream query/ground-truth pairs are ranked by a fixed SHA-256 seed and split into 200 calibration queries and 800 publication queries. Their exact overlap is zero; both partition fingerprints are retained.

Each engine/workload trial has one fresh service and one fixed index lifecycle:

  1. Start lifecycle memory sampling before indexing.
  2. Load and build the index once using fixed construction parameters.
  3. Sweep only the query-time parameter on the 200-query calibration partition.
  4. Freeze the lowest setting reaching recall 0.955. If none qualifies, retain the highest-recall setting and mark it below the qualification floor.
  5. Without rebuilding, run the selected setting on the untouched 800-query partition at 1, 5, 10, 20, and 30 concurrent clients for 30 seconds each, followed by the upstream serial quality and latency pass.
  6. Capture one diagnostic post-workload storage observation, gracefully stop and verify the service, capture final storage, retain the artifacts, and only then reclaim the engine’s data.

The 50K and 1M settings are selected independently because the larger graph may need a higher search setting. Publication results never influence selection. A row below the 0.950 publication floor remains visible and is not silently retuned or omitted. No process-restart measurement is published.

Tuned and fixed parameters

EngineFixed index/build parametersQuery-time selection
AntflyAKNN, one shard, packed float32 queriessearch_effort sweep
MilvusHNSW M=16, efConstruction=256ef_search sweep
ChromaHNSW M=16, efConstruction=256fixed ef_search=256 qualification
WeaviateHNSW maxConnections=16, efConstruction=256ef sweep
pgvectorHNSW m=16, ef_construction=128ef_search sweep
ElasticsearchHNSW m=16, ef_construction=100num_candidates sweep

The final report prints the selected value for every workload and engine. Weaviate and Elasticsearch are local containers; their upstream adapter class names (WeaviateCloud and ElasticCloud) do not describe the deployment.

Memory

The table reports both memory views. Demand working set is the maximum sampled cgroup-v2 anon + shmem from before indexing through readiness, calibration, and publication queries; it excludes reclaimable file cache and follows MEASURING_ANTFLY.md. Cache-inclusive peak is the maximum concurrently sampled sum of memory.current across the complete service stack and includes file cache and cgroup-charged kernel memory. Sampling runs every 200 ms and retains the timeline. Kernel memory.peak is also retained as an exact peak for a single cgroup, or a conservative sum of independent peaks for a multi-container stack.

Honed publication requires three fresh lifecycles per engine/workload. The headline table shows each arithmetic mean; detail artifacts retain every observation, the mean, and the individual-trial range. A trial is rejected if the canonical sampler reports a failure, misses any container in the service stack, starts after indexing, stops before publication finishes, or leaves a timeline gap above five seconds. Peak throughput, its concurrency, C=30 throughput and concurrent p99, recall, nDCG, serial latency, and memory are arithmetic means of the three compatible lifecycle observations. Raw curves and ranges remain retained. The selected setting and protocol identity must match across all three trials.

The complete Antfly standalone container is measured, so all Antfly processes and threads in that cgroup are included. Termite is not part of this workload because VectorDBBench supplies precomputed vectors.

Persistent database volume

Every publication engine receives one newly created, run-labeled Docker local volume at its complete persistence root. The digest-pinned Alpine probe captures whole-volume allocated and apparent bytes once at empty, ready, and post_workload, then at the verified post-stop final barrier. Host-path/no-network Antfly is rejected for comparative storage. Pre-stop background compaction remains diagnostic and does not gate the post-stop metric.

Final allocated bytes are the headline. The same three construction lifecycles define performance, memory, and storage aggregates. Every value, arithmetic mean, range, receipt, and barrier sample remains under raw/storage.

Internal Antfly scale diagnostic

make vdbbench-scale-fast and make vdbbench-scale-big run an Antfly-only diagnostic beside the cross-engine publication matrix. The fast profile uses 20K, 40K, 60K, 80K, and 100K vectors; the big profile uses 200K, 400K, 600K, 800K, and 1M vectors. make vdbbench-scale selects both. All points use 768 dimensions and the same 200-query calibration partition, disjoint 800-query held-out partition, serial pass, and 1/5/10/20/30-client 30-second capped sweep described above.

The diagnostic has exactly two fresh index lifecycles per point. Trial one runs from the smallest to largest selected corpus; trial two reverses that order. This controls simple order effects without claiming the three-lifecycle publication cohort. The aggregate and every row set publication_eligible: false, retain both raw values plus their arithmetic mean and range, and state the two-lifecycle caveat. Scale results must not be merged into the honed cross-engine cohort.

The source corpus is the pinned upstream Cohere 768-dimensional 1M-vector fixture. Circus verifies its immutable source files, computes exact cosine top-k ground truth against deterministic prefix sizes, and writes explicit custom-dataset manifests. A streaming iterator is bounded by the manifest’s declared prefix size; a smaller point cannot consume rows belonging to a larger shared Parquet file.

Each point/trial is an immutable publication-cache cell with workload-specific dataset identity. A cache miss receives one fresh retry, never an in-place resume. Only a complete positive lifecycle or a classified held-out capacity/rejection result can be promoted. The canonical diagnostic artifact retains every cell’s receipt/cache reference, query-partition digest, selected search effort, request-error evidence, memory timeline, final allocated volume, and insert_duration + optimize_duration build time.

Output and retention

The canonical artifact contains report.md, normalized result.json, provenance, a receipt, selected settings, the raw capped-concurrency JSON/CSV diagnostic, memory rows and timelines, logs, supervisor/status evidence, and upstream result JSON. Standard publication runs VectorDBBench’s increasing concurrency progression at 1, 5, 10, 20, and 30 clients. Normalized rows report peak QPS and its concurrency as well as qps_c30 and p99_c30_ms.

A lifecycle that completes the selected-setting, held-out capped sweep but has explicit nonzero request rejections is retained as a classified capacity terminal negative. It is reusable only with the exact concurrency schedule, query partition, selected setting, full memory timeline, quiet-host assertion, logs, and supervisor evidence. Setup/index/configuration failures, crashes, timeouts, partial lifecycles, and unknown failures are never reusable publication cells. Database volumes are deleted only after the verified final capture unless an operator explicitly opts into retaining them for debugging. The retained storage.json receipt and complete optional-trial evidence are results; the live volume is not.

Run evidence parameters · variation · provenance

Benchmark parameters

{"concurrency_duration_seconds":30,"concurrency_schedule":[1,5,10,20,30],"query_count":800,"workloads":["1536d-50K"]}

Trial variation

[{"engine":"Antfly","ranges":{"demand_working_set":{"maximum":1849.2,"mean":1747.9,"minimum":1649.5,"unit":"MB"},"final_database_volume":{"maximum":356.687872,"mean":356.223659,"minimum":355.975168,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":42.8,"mean":41.633,"minimum":40.8,"unit":"ms"}},"workload":"1536d-50K"},{"engine":"Chroma","ranges":{"demand_working_set":{"maximum":468.9,"mean":463.3,"minimum":455.4,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":176.7,"mean":176.467,"minimum":176.3,"unit":"ms"}},"workload":"1536d-50K"},{"engine":"ElasticCloud","ranges":{"demand_working_set":{"maximum":1871.2,"mean":1861.3,"minimum":1854.6,"unit":"MB"},"final_database_volume":{"maximum":312.430592,"mean":312.380075,"minimum":312.352768,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":13.7,"mean":13.5,"minimum":13.4,"unit":"ms"}},"workload":"1536d-50K"},{"engine":"Milvus","ranges":{"demand_working_set":{"maximum":2577.1,"mean":2490.3,"minimum":2428.4,"unit":"MB"},"final_database_volume":{"maximum":1741.217792,"mean":1741.202773,"minimum":1741.193216,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":10.6,"mean":10.433,"minimum":10.3,"unit":"ms"}},"workload":"1536d-50K"},{"engine":"PgVector","ranges":{"demand_working_set":{"maximum":2303.9,"mean":2303.8,"minimum":2303.7,"unit":"MB"},"final_database_volume":{"maximum":1523.970048,"mean":1523.965952,"minimum":1523.961856,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":35.6,"mean":33.7,"minimum":32.6,"unit":"ms"}},"workload":"1536d-50K"},{"engine":"WeaviateCloud","ranges":{"demand_working_set":{"maximum":965.9,"mean":938.5,"minimum":912.1,"unit":"MB"},"final_database_volume":{"maximum":391.360512,"mean":391.277227,"minimum":391.172096,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":86.5,"mean":85.533,"minimum":83.7,"unit":"ms"}},"workload":"1536d-50K"}]

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
e599c852ae6c1544b8fd5c41183b3b56fc5a5ef894b2643be94b6da83a550a09
Aggregate
809572e4fcec1c0b928f2f0cf1d7670e3724d06e2a5619852ed1b47eaafa2d3e
Provenance
00db9a59f839aabdd0cc506f6e04b1316b4859b9e9a6de41285f179926741a31
Harness commit
a379ba64c66bfa7f2468d1fcfc78d3e79a32f639

Scope notes

  • Chroma 50K storage is unavailable: the harness measured an unused volume rather than the database path persisted by the pinned image.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
3h 21m 2s
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

Chroma 50K storage is unavailable: the harness measured an unused volume rather than the database path persisted by the pinned image.

Peak throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 1536d-50K · Higher is better

Serial query p95

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 1536d-50K · Lower is better

Demand working set

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 1536d-50K · Lower is better

Final database volume

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 1536d-50K · Lower is better

Performance, quality, and resource evidence

Antfly v0.2.0 · 56a1b1a5

EngineWorkloadRecallnDCGPeak QPS queries/sp95 msDemand working set MBCache-inclusive peak MBFinal database volume MBTrials
Antfly1536d-50K0.9590.9641,727.731,747.9 MB2,213.6 MB356.2 MB3
Chroma1536d-50K0.9870.989179.98.07463.3 MB809.2 MBNot recorded MB3
ElasticCloud1536d-50K0.9600.9674,600.11.971,861.3 MB4,318.4 MB312.4 MB3
Milvus1536d-50K0.9630.9705,643.11.502,490.3 MB4,565.6 MB1,741.2 MB3
PgVector1536d-50K0.9690.9752,432.34.172,303.8 MB3,265.2 MB1,524.0 MB3
WeaviateCloud1536d-50K0.9550.963995.66.60938.5 MB1,553.7 MB391.3 MB3
ii

vector-vdbbench-1m

complete

1M

Reviewed 1M vector search quality, throughput, latency, serving demand, and valid database volume evidence.

Methodology scope · protocol · interpretation

VectorDBBench methodology

Antfly subject and execution lane

Circus accepts an explicit subject manifest containing the asserted release tag, commit, and Linux/arm64 Antfly binary. It records the binary path, SHA-256, architecture, and observed --version output, while treating the supplied tag and commit as release metadata. The honed matrix mounts that binary read-only into Antfly’s Linux container. Every comparison engine runs in the same private Docker network; no native macOS database is mixed into this benchmark.

The public benchmarks/VectorDBBench checkout remains clean. Circus-owned parameter selection, compatibility fixes, query partitioning, and diagnostics live in benchmarks/VectorDBBench-harness and are loaded as a runtime overlay.

Workloads and query protocol

The publication matrix contains six engines on both upstream workloads:

  • Performance1536D50K: 50,000 vectors with 1,536 dimensions.
  • Performance768D1M: 1,000,000 vectors with 768 dimensions.

For each workload, the 1,000 upstream query/ground-truth pairs are ranked by a fixed SHA-256 seed and split into 200 calibration queries and 800 publication queries. Their exact overlap is zero; both partition fingerprints are retained.

Each engine/workload trial has one fresh service and one fixed index lifecycle:

  1. Start lifecycle memory sampling before indexing.
  2. Load and build the index once using fixed construction parameters.
  3. Sweep only the query-time parameter on the 200-query calibration partition.
  4. Freeze the lowest setting reaching recall 0.955. If none qualifies, retain the highest-recall setting and mark it below the qualification floor.
  5. Without rebuilding, run the selected setting on the untouched 800-query partition at 1, 5, 10, 20, and 30 concurrent clients for 30 seconds each, followed by the upstream serial quality and latency pass.
  6. Capture one diagnostic post-workload storage observation, gracefully stop and verify the service, capture final storage, retain the artifacts, and only then reclaim the engine’s data.

The 50K and 1M settings are selected independently because the larger graph may need a higher search setting. Publication results never influence selection. A row below the 0.950 publication floor remains visible and is not silently retuned or omitted. No process-restart measurement is published.

Tuned and fixed parameters

EngineFixed index/build parametersQuery-time selection
AntflyAKNN, one shard, packed float32 queriessearch_effort sweep
MilvusHNSW M=16, efConstruction=256ef_search sweep
ChromaHNSW M=16, efConstruction=256fixed ef_search=256 qualification
WeaviateHNSW maxConnections=16, efConstruction=256ef sweep
pgvectorHNSW m=16, ef_construction=128ef_search sweep
ElasticsearchHNSW m=16, ef_construction=100num_candidates sweep

The final report prints the selected value for every workload and engine. Weaviate and Elasticsearch are local containers; their upstream adapter class names (WeaviateCloud and ElasticCloud) do not describe the deployment.

Memory

The table reports both memory views. Demand working set is the maximum sampled cgroup-v2 anon + shmem from before indexing through readiness, calibration, and publication queries; it excludes reclaimable file cache and follows MEASURING_ANTFLY.md. Cache-inclusive peak is the maximum concurrently sampled sum of memory.current across the complete service stack and includes file cache and cgroup-charged kernel memory. Sampling runs every 200 ms and retains the timeline. Kernel memory.peak is also retained as an exact peak for a single cgroup, or a conservative sum of independent peaks for a multi-container stack.

Honed publication requires three fresh lifecycles per engine/workload. The headline table shows each arithmetic mean; detail artifacts retain every observation, the mean, and the individual-trial range. A trial is rejected if the canonical sampler reports a failure, misses any container in the service stack, starts after indexing, stops before publication finishes, or leaves a timeline gap above five seconds. Peak throughput, its concurrency, C=30 throughput and concurrent p99, recall, nDCG, serial latency, and memory are arithmetic means of the three compatible lifecycle observations. Raw curves and ranges remain retained. The selected setting and protocol identity must match across all three trials.

The complete Antfly standalone container is measured, so all Antfly processes and threads in that cgroup are included. Termite is not part of this workload because VectorDBBench supplies precomputed vectors.

Persistent database volume

Every publication engine receives one newly created, run-labeled Docker local volume at its complete persistence root. The digest-pinned Alpine probe captures whole-volume allocated and apparent bytes once at empty, ready, and post_workload, then at the verified post-stop final barrier. Host-path/no-network Antfly is rejected for comparative storage. Pre-stop background compaction remains diagnostic and does not gate the post-stop metric.

Final allocated bytes are the headline. The same three construction lifecycles define performance, memory, and storage aggregates. Every value, arithmetic mean, range, receipt, and barrier sample remains under raw/storage.

Internal Antfly scale diagnostic

make vdbbench-scale-fast and make vdbbench-scale-big run an Antfly-only diagnostic beside the cross-engine publication matrix. The fast profile uses 20K, 40K, 60K, 80K, and 100K vectors; the big profile uses 200K, 400K, 600K, 800K, and 1M vectors. make vdbbench-scale selects both. All points use 768 dimensions and the same 200-query calibration partition, disjoint 800-query held-out partition, serial pass, and 1/5/10/20/30-client 30-second capped sweep described above.

The diagnostic has exactly two fresh index lifecycles per point. Trial one runs from the smallest to largest selected corpus; trial two reverses that order. This controls simple order effects without claiming the three-lifecycle publication cohort. The aggregate and every row set publication_eligible: false, retain both raw values plus their arithmetic mean and range, and state the two-lifecycle caveat. Scale results must not be merged into the honed cross-engine cohort.

The source corpus is the pinned upstream Cohere 768-dimensional 1M-vector fixture. Circus verifies its immutable source files, computes exact cosine top-k ground truth against deterministic prefix sizes, and writes explicit custom-dataset manifests. A streaming iterator is bounded by the manifest’s declared prefix size; a smaller point cannot consume rows belonging to a larger shared Parquet file.

Each point/trial is an immutable publication-cache cell with workload-specific dataset identity. A cache miss receives one fresh retry, never an in-place resume. Only a complete positive lifecycle or a classified held-out capacity/rejection result can be promoted. The canonical diagnostic artifact retains every cell’s receipt/cache reference, query-partition digest, selected search effort, request-error evidence, memory timeline, final allocated volume, and insert_duration + optimize_duration build time.

Output and retention

The canonical artifact contains report.md, normalized result.json, provenance, a receipt, selected settings, the raw capped-concurrency JSON/CSV diagnostic, memory rows and timelines, logs, supervisor/status evidence, and upstream result JSON. Standard publication runs VectorDBBench’s increasing concurrency progression at 1, 5, 10, 20, and 30 clients. Normalized rows report peak QPS and its concurrency as well as qps_c30 and p99_c30_ms.

A lifecycle that completes the selected-setting, held-out capped sweep but has explicit nonzero request rejections is retained as a classified capacity terminal negative. It is reusable only with the exact concurrency schedule, query partition, selected setting, full memory timeline, quiet-host assertion, logs, and supervisor evidence. Setup/index/configuration failures, crashes, timeouts, partial lifecycles, and unknown failures are never reusable publication cells. Database volumes are deleted only after the verified final capture unless an operator explicitly opts into retaining them for debugging. The retained storage.json receipt and complete optional-trial evidence are results; the live volume is not.

Run evidence parameters · variation · provenance

Benchmark parameters

{"concurrency_duration_seconds":30,"concurrency_schedule":[1,5,10,20,30],"query_count":800,"workloads":["768d-1M"]}

Trial variation

[{"engine":"Antfly","ranges":{"demand_working_set":{"maximum":8470.1,"mean":8012.1,"minimum":7559.7,"unit":"MB"},"final_database_volume":{"maximum":3874.67264,"mean":3864.095403,"minimum":3858.550784,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":2160.4,"mean":1454.833,"minimum":446.9,"unit":"ms"}},"workload":"768d-1M"},{"engine":"Chroma","ranges":{"demand_working_set":{"maximum":3697.5,"mean":3690.9,"minimum":3684.1,"unit":"MB"},"final_database_volume":{"maximum":3460.145152,"mean":3459.732821,"minimum":3459.108864,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":167.7,"mean":148.833,"minimum":134.9,"unit":"ms"}},"workload":"768d-1M"},{"engine":"ElasticCloud","ranges":{"demand_working_set":{"maximum":2153.7,"mean":2088.4,"minimum":2035.2,"unit":"MB"},"final_database_volume":{"maximum":3153.5104,"mean":3153.36704,"minimum":3153.240064,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":19.5,"mean":19.4,"minimum":19.3,"unit":"ms"}},"workload":"768d-1M"},{"engine":"Milvus","ranges":{"demand_working_set":{"maximum":9128.1,"mean":8882,"minimum":8741.6,"unit":"MB"},"final_database_volume":{"maximum":19268.632576,"mean":19125.717675,"minimum":19050.5984,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":19.6,"mean":19.067,"minimum":18.7,"unit":"ms"}},"workload":"768d-1M"},{"engine":"PgVector","ranges":{"demand_working_set":{"maximum":2321.2,"mean":2318.7,"minimum":2316.4,"unit":"MB"},"final_database_volume":{"maximum":9329.483776,"mean":9329.455104,"minimum":9329.422336,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":78.2,"mean":77.033,"minimum":74.7,"unit":"ms"}},"workload":"768d-1M"},{"engine":"WeaviateCloud","ranges":{"demand_working_set":{"maximum":7339.2,"mean":7325.5,"minimum":7312.2,"unit":"MB"},"final_database_volume":{"maximum":4101.083136,"mean":4096.404139,"minimum":4091.887616,"unit":"MB"},"p99_at_peak_concurrency":{"maximum":77.2,"mean":75.6,"minimum":74.3,"unit":"ms"}},"workload":"768d-1M"}]

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
9f8d6cf223ac10dc3722f7754de27973f6abc76f395395f48be51b68bcb0d146
Aggregate
2f9311d8e7bc67de25c17d2c13be9a0550b8123e73c3c2429d77a5eec5ca98d3
Provenance
e73dd7891b85149712664234ff01476ee63f88877d62f1c983ea4a320b0f1c54
Harness commit
0719517552c4fad3dc726aff366c2a13e7308fff
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
8h 52m 23s
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Peak throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 768d-1M · Higher is better

Serial query p95

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 768d-1M · Lower is better

Demand working set

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 768d-1M · Lower is better

Final database volume

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 768d-1M · Lower is better

Performance, quality, and resource evidence

Antfly v0.2.0 · 56a1b1a5

EngineWorkloadRecallnDCGPeak QPS queries/sp95 msDemand working set MBCache-inclusive peak MBFinal database volume MBTrials
Antfly768d-1M0.9600.964136.779.678,012.1 MB17,196.2 MB3,864.1 MB3
Chroma768d-1M0.9560.962237.66.903,690.9 MB7,276 MB3,459.7 MB3
ElasticCloud768d-1M0.9600.9633,401.82.932,088.4 MB15,188.7 MB3,153.4 MB3
Milvus768d-1M0.9620.9652,570.11.878,882 MB21,448.9 MB19,125.7 MB3
PgVector768d-1M0.9660.970850.910.702,318.7 MB11,985.1 MB9,329.5 MB3
WeaviateCloud768d-1M0.9560.9621,163.66.637,325.5 MB13,540.2 MB4,096.4 MB3
iii

vector-vdbbench-scale

missing

Scale

Five-point Antfly scale diagnostics for indexing time, quality, throughput, latency, serving demand, and database volume.

Methodology scope · protocol · interpretation

VectorDBBench methodology

Antfly subject and execution lane

Circus accepts an explicit subject manifest containing the asserted release tag, commit, and Linux/arm64 Antfly binary. It records the binary path, SHA-256, architecture, and observed --version output, while treating the supplied tag and commit as release metadata. The honed matrix mounts that binary read-only into Antfly’s Linux container. Every comparison engine runs in the same private Docker network; no native macOS database is mixed into this benchmark.

The public benchmarks/VectorDBBench checkout remains clean. Circus-owned parameter selection, compatibility fixes, query partitioning, and diagnostics live in benchmarks/VectorDBBench-harness and are loaded as a runtime overlay.

Workloads and query protocol

The publication matrix contains six engines on both upstream workloads:

  • Performance1536D50K: 50,000 vectors with 1,536 dimensions.
  • Performance768D1M: 1,000,000 vectors with 768 dimensions.

For each workload, the 1,000 upstream query/ground-truth pairs are ranked by a fixed SHA-256 seed and split into 200 calibration queries and 800 publication queries. Their exact overlap is zero; both partition fingerprints are retained.

Each engine/workload trial has one fresh service and one fixed index lifecycle:

  1. Start lifecycle memory sampling before indexing.
  2. Load and build the index once using fixed construction parameters.
  3. Sweep only the query-time parameter on the 200-query calibration partition.
  4. Freeze the lowest setting reaching recall 0.955. If none qualifies, retain the highest-recall setting and mark it below the qualification floor.
  5. Without rebuilding, run the selected setting on the untouched 800-query partition at 1, 5, 10, 20, and 30 concurrent clients for 30 seconds each, followed by the upstream serial quality and latency pass.
  6. Capture one diagnostic post-workload storage observation, gracefully stop and verify the service, capture final storage, retain the artifacts, and only then reclaim the engine’s data.

The 50K and 1M settings are selected independently because the larger graph may need a higher search setting. Publication results never influence selection. A row below the 0.950 publication floor remains visible and is not silently retuned or omitted. No process-restart measurement is published.

Tuned and fixed parameters

EngineFixed index/build parametersQuery-time selection
AntflyAKNN, one shard, packed float32 queriessearch_effort sweep
MilvusHNSW M=16, efConstruction=256ef_search sweep
ChromaHNSW M=16, efConstruction=256fixed ef_search=256 qualification
WeaviateHNSW maxConnections=16, efConstruction=256ef sweep
pgvectorHNSW m=16, ef_construction=128ef_search sweep
ElasticsearchHNSW m=16, ef_construction=100num_candidates sweep

The final report prints the selected value for every workload and engine. Weaviate and Elasticsearch are local containers; their upstream adapter class names (WeaviateCloud and ElasticCloud) do not describe the deployment.

Memory

The table reports both memory views. Demand working set is the maximum sampled cgroup-v2 anon + shmem from before indexing through readiness, calibration, and publication queries; it excludes reclaimable file cache and follows MEASURING_ANTFLY.md. Cache-inclusive peak is the maximum concurrently sampled sum of memory.current across the complete service stack and includes file cache and cgroup-charged kernel memory. Sampling runs every 200 ms and retains the timeline. Kernel memory.peak is also retained as an exact peak for a single cgroup, or a conservative sum of independent peaks for a multi-container stack.

Honed publication requires three fresh lifecycles per engine/workload. The headline table shows each arithmetic mean; detail artifacts retain every observation, the mean, and the individual-trial range. A trial is rejected if the canonical sampler reports a failure, misses any container in the service stack, starts after indexing, stops before publication finishes, or leaves a timeline gap above five seconds. Peak throughput, its concurrency, C=30 throughput and concurrent p99, recall, nDCG, serial latency, and memory are arithmetic means of the three compatible lifecycle observations. Raw curves and ranges remain retained. The selected setting and protocol identity must match across all three trials.

The complete Antfly standalone container is measured, so all Antfly processes and threads in that cgroup are included. Termite is not part of this workload because VectorDBBench supplies precomputed vectors.

Persistent database volume

Every publication engine receives one newly created, run-labeled Docker local volume at its complete persistence root. The digest-pinned Alpine probe captures whole-volume allocated and apparent bytes once at empty, ready, and post_workload, then at the verified post-stop final barrier. Host-path/no-network Antfly is rejected for comparative storage. Pre-stop background compaction remains diagnostic and does not gate the post-stop metric.

Final allocated bytes are the headline. The same three construction lifecycles define performance, memory, and storage aggregates. Every value, arithmetic mean, range, receipt, and barrier sample remains under raw/storage.

Internal Antfly scale diagnostic

make vdbbench-scale-fast and make vdbbench-scale-big run an Antfly-only diagnostic beside the cross-engine publication matrix. The fast profile uses 20K, 40K, 60K, 80K, and 100K vectors; the big profile uses 200K, 400K, 600K, 800K, and 1M vectors. make vdbbench-scale selects both. All points use 768 dimensions and the same 200-query calibration partition, disjoint 800-query held-out partition, serial pass, and 1/5/10/20/30-client 30-second capped sweep described above.

The diagnostic has exactly two fresh index lifecycles per point. Trial one runs from the smallest to largest selected corpus; trial two reverses that order. This controls simple order effects without claiming the three-lifecycle publication cohort. The aggregate and every row set publication_eligible: false, retain both raw values plus their arithmetic mean and range, and state the two-lifecycle caveat. Scale results must not be merged into the honed cross-engine cohort.

The source corpus is the pinned upstream Cohere 768-dimensional 1M-vector fixture. Circus verifies its immutable source files, computes exact cosine top-k ground truth against deterministic prefix sizes, and writes explicit custom-dataset manifests. A streaming iterator is bounded by the manifest’s declared prefix size; a smaller point cannot consume rows belonging to a larger shared Parquet file.

Each point/trial is an immutable publication-cache cell with workload-specific dataset identity. A cache miss receives one fresh retry, never an in-place resume. Only a complete positive lifecycle or a classified held-out capacity/rejection result can be promoted. The canonical diagnostic artifact retains every cell’s receipt/cache reference, query-partition digest, selected search effort, request-error evidence, memory timeline, final allocated volume, and insert_duration + optimize_duration build time.

Output and retention

The canonical artifact contains report.md, normalized result.json, provenance, a receipt, selected settings, the raw capped-concurrency JSON/CSV diagnostic, memory rows and timelines, logs, supervisor/status evidence, and upstream result JSON. Standard publication runs VectorDBBench’s increasing concurrency progression at 1, 5, 10, 20, and 30 clients. Normalized rows report peak QPS and its concurrency as well as qps_c30 and p99_c30_ms.

A lifecycle that completes the selected-setting, held-out capped sweep but has explicit nonzero request rejections is retained as a classified capacity terminal negative. It is reusable only with the exact concurrency schedule, query partition, selected setting, full memory timeline, quiet-host assertion, logs, and supervisor evidence. Setup/index/configuration failures, crashes, timeouts, partial lifecycles, and unknown failures are never reusable publication cells. Database volumes are deleted only after the verified final capture unless an operator explicitly opts into retaining them for debugging. The retained storage.json receipt and complete optional-trial evidence are results; the live volume is not.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
II

inference-termite-circus

partial

Termite inference

Independent model and provider capability, performance, quality, and memory evidence for the model-serving path shipped with v0.2.0.

Methodology scope · protocol · interpretation

Antfly Inference Methodology

Subject contract

Inference is delegated to ../termite-circus. Each campaign receives exactly one explicit ANTFLY_BIN from the antfly-circus subject manifest. The harness records the executable’s version, architecture, and SHA-256; it does not fetch, install, update, or build Antfly. Comparing Antfly releases means comparing separate campaign bundles.

The rc.24 acceptance matrix covers generation, dense/sparse/multimodal embedding, reranking, chunking, GLiNER2 extraction, OCR/readers, and transcription. Rewriters are reported as known-incompatible rather than timed.

Profiles

  • smoke runs only the supplied Antfly binary, one lifecycle and one measured request, against one certified representative per working category. It is a compatibility gate, not publication evidence.
  • full adds category-appropriate local reference runtimes and certified model alternates. Each provider/model cell uses three fresh lifecycles, one warmup per lifecycle, and the tracked request count from matrix.json. Provider order alternates to reduce order bias.

Reference runtimes are local only: llama.cpp, Ollama, and vLLM-Metal for generation; ONNX Runtime and Sentence Transformers for embedding/reranking; GLiNER2 for extraction; Transformers for Florence-2; and faster-whisper plus whisper.cpp for transcription.

Provider-native formats are permitted when a runtime cannot load an identical artifact. Every result retains the logical model, exact artifact/revision, variant or quantization, and checksum. Such rows are not described as byte-identical comparisons.

Validity and metrics

Every cell must pass a deterministic category-specific quality gate before its latency or throughput is valid. The gates check semantic ordering, sparse output, cross-modal output, relevant-document ordering, valid chunk coverage, expected extraction fields, OCR/transcription word recovery, or a nonempty constrained completion. These fixtures detect broken inference; they are not a general model-quality leaderboard.

Warm request latency is reported as p50 and p95 within measured requests. Throughput uses successful measured requests only. Cold model-load/readiness time and raw provider output remain in the campaign artifacts rather than being mixed into warm latency.

Peak inference memory is the maximum of two concurrently sampled views:

  1. rooted process-tree RSS, including provider helpers and model servers;
  2. positive growth in system anonymous + compressor-occupied + wired memory from the pre-launch baseline.

Samples are retained every 200 ms. System growth is publishable only when the operator sets QUIET_HOST_ACK=1 on a quiet host; otherwise the memory value is diagnostic. Full reports retain each lifecycle and report the arithmetic mean and range rather than selecting the best trial.

Artifacts

The full antfly-circus command writes directly into $BASTILLE_OUT/data/inference-termite-circus/:

  • report.md: compact per-category tables;
  • result.json: canonical normalized rows consumed by antfly-circus;
  • provenance.json: subject, host, model, provider, and input fingerprints;
  • receipt.json: completeness, failures, and quality-gate status;
  • raw/: provider logs and memory timelines.

A failed campaign still retains the bundle and failed rows. Publication reads result.json and the receipt; Markdown is derived output and is never parsed as the source of truth.

Run evidence parameters · variation · provenance

Benchmark parameters

{"chart_representatives":[{"benchmark_id":"generation-gemma4-e4b","category":"generation","model":"ggml-org/gemma-4-E4B-it-GGUF","variants":["Q4_0"]},{"benchmark_id":"dense-bge-small","category":"dense embedding","model":"BAAI/bge-small-en-v1.5","variants":["f32"]},{"benchmark_id":"sparse-splade-tiny","category":"sparse embedding","model":"sparse-encoder-testing/splade-bert-tiny-nq-onnx","variants":["onnx"]},{"benchmark_id":"multimodal-clipclap","category":"multimodal embedding","model":"antflydb/clipclap","variants":["Q4_K"]},{"benchmark_id":"rerank-mxbai-base","category":"reranking","model":"mixedbread-ai/mxbai-rerank-base-v1","variants":["f32"]},{"benchmark_id":"chunk-chonky","category":"chunking","model":"mirth/chonky_mmbert_small_multilingual_1","variants":["f32"]},{"benchmark_id":"extract-gliner2-base","category":"extraction","model":"antflydb/gliner2-base-v1","variants":["f32"]},{"benchmark_id":"ocr-florence2-base","category":"reading / OCR","model":"antflydb/Florence-2-base","variants":["f32"]},{"benchmark_id":"transcribe-whisper-tiny","category":"transcription","model":"openai/whisper-tiny","variants":["f32"]}],"measured_rows":37,"model_provider_rows":44,"unmeasured_rows":7}

Trial variation

[{"model":"unsloth/Qwen3-1.7B-GGUF","peak_memory":{"maximum":9802.0625,"mean":7297.526041666667,"minimum":5963.21875,"unit":"MB"},"provider":"antfly","variant":"Q4_K_M"},{"model":"BAAI/bge-small-en-v1.5","peak_memory":{"maximum":769.515625,"mean":752.8229166666666,"minimum":742,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"BAAI/bge-large-en-v1.5","peak_memory":{"maximum":3018,"mean":2904.2395833333335,"minimum":2843.484375,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"mixedbread-ai/mxbai-embed-large-v1","peak_memory":{"maximum":2862.296875,"mean":2836.546875,"minimum":2810.1875,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"antflydb/clipclap","peak_memory":{"maximum":572.65625,"mean":523.5364583333334,"minimum":428.515625,"unit":"MB"},"provider":"antfly","variant":"Q4_K"},{"model":"mixedbread-ai/mxbai-rerank-base-v1","peak_memory":{"maximum":1925.703125,"mean":1767.5989583333333,"minimum":1624.109375,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"cross-encoder/ms-marco-MiniLM-L6-v2","peak_memory":{"maximum":653.96875,"mean":625.21875,"minimum":606.984375,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"fixed_bert","peak_memory":{"maximum":402.875,"mean":353.2552083333333,"minimum":328.171875,"unit":"MB"},"provider":"antfly","variant":"built-in"},{"model":"fixed_bpe","peak_memory":{"maximum":555.78125,"mean":402.9479166666667,"minimum":326.453125,"unit":"MB"},"provider":"antfly","variant":"built-in"},{"model":"mirth/chonky_mmbert_small_multilingual_1","peak_memory":{"maximum":351.03125,"mean":334.1510416666667,"minimum":323,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"antflydb/gliner2-base-v1","peak_memory":{"maximum":1046.90625,"mean":1015.4427083333334,"minimum":984.015625,"unit":"MB"},"provider":"antfly","variant":"f32"},{"model":"ggml-org/gemma-4-E4B-it-GGUF","peak_memory":{"maximum":7726.65625,"mean":7434.364583333333,"minimum":7111,"unit":"MB"},"provider":"llama.cpp","variant":"Q4_0"},{"model":"ggml-org/gemma-4-E4B-it-GGUF","peak_memory":{"maximum":11632.296875,"mean":10929.015625,"minimum":10415.78125,"unit":"MB"},"provider":"ollama","variant":"Q4_0"},{"model":"ggml-org/gemma-4-E4B-it-GGUF","peak_memory":{"maximum":27998.640625,"mean":25524.130208333332,"minimum":20975.46875,"unit":"MB"},"provider":"vllm-metal","variant":"Q4_0"},{"model":"google/gemma-4-E4B-it-qat-q4_0-gguf","peak_memory":{"maximum":8404.0625,"mean":7605.09375,"minimum":7201.640625,"unit":"MB"},"provider":"llama.cpp","variant":"QAT q4_0"},{"model":"google/gemma-4-E4B-it-qat-q4_0-gguf","peak_memory":{"maximum":7804.75,"mean":7387.28125,"minimum":6806.921875,"unit":"MB"},"provider":"ollama","variant":"QAT q4_0"},{"model":"google/gemma-4-E4B-it-qat-q4_0-gguf","peak_memory":{"maximum":28953.59375,"mean":28351.203125,"minimum":28043.796875,"unit":"MB"},"provider":"vllm-metal","variant":"QAT q4_0"},{"model":"unsloth/Qwen3-1.7B-GGUF","peak_memory":{"maximum":5665.421875,"mean":5665.348958333333,"minimum":5665.25,"unit":"MB"},"provider":"llama.cpp","variant":"Q4_K_M"},{"model":"unsloth/Qwen3-1.7B-GGUF","peak_memory":{"maximum":5348.796875,"mean":5162.703125,"minimum":5059.1875,"unit":"MB"},"provider":"ollama","variant":"Q4_K_M"},{"model":"unsloth/Qwen3-1.7B-GGUF","peak_memory":{"maximum":28489.640625,"mean":25832.145833333332,"minimum":24216.65625,"unit":"MB"},"provider":"vllm-metal","variant":"Q4_K_M"},{"model":"BAAI/bge-small-en-v1.5","peak_memory":{"maximum":1027.65625,"mean":1024.2864583333333,"minimum":1022.125,"unit":"MB"},"provider":"onnxruntime","variant":"f32"},{"model":"BAAI/bge-small-en-v1.5","peak_memory":{"maximum":1734.4375,"mean":1296.7708333333333,"minimum":531.328125,"unit":"MB"},"provider":"sentence-transformers","variant":"f32"},{"model":"BAAI/bge-large-en-v1.5","peak_memory":{"maximum":3448.859375,"mean":3448.4322916666665,"minimum":3448.21875,"unit":"MB"},"provider":"onnxruntime","variant":"f32"},{"model":"BAAI/bge-large-en-v1.5","peak_memory":{"maximum":3779.78125,"mean":2297.2447916666665,"minimum":534.21875,"unit":"MB"},"provider":"sentence-transformers","variant":"f32"},{"model":"mixedbread-ai/mxbai-embed-large-v1","peak_memory":{"maximum":3447.1875,"mean":3446.8854166666665,"minimum":3446.671875,"unit":"MB"},"provider":"onnxruntime","variant":"f32"},{"model":"mixedbread-ai/mxbai-embed-large-v1","peak_memory":{"maximum":3188.9375,"mean":2633.1770833333335,"minimum":1609.125,"unit":"MB"},"provider":"sentence-transformers","variant":"f32"},{"model":"sparse-encoder-testing/splade-bert-tiny-nq-onnx","peak_memory":{"maximum":630.59375,"mean":628.4947916666666,"minimum":626.75,"unit":"MB"},"provider":"onnxruntime","variant":"onnx"},{"model":"sparse-encoder-testing/splade-bert-tiny-nq-onnx","peak_memory":{"maximum":1570.609375,"mean":1275.5416666666667,"minimum":707,"unit":"MB"},"provider":"sentence-transformers","variant":"onnx"},{"model":"mixedbread-ai/mxbai-rerank-base-v1","peak_memory":{"maximum":4774.015625,"mean":4766.505208333333,"minimum":4760.4375,"unit":"MB"},"provider":"onnxruntime","variant":"f32"},{"model":"mixedbread-ai/mxbai-rerank-base-v1","peak_memory":{"maximum":2340.1875,"mean":1827.171875,"minimum":1177.53125,"unit":"MB"},"provider":"sentence-transformers","variant":"f32"},{"model":"cross-encoder/ms-marco-MiniLM-L6-v2","peak_memory":{"maximum":962.453125,"mean":960.0885416666666,"minimum":958.375,"unit":"MB"},"provider":"onnxruntime","variant":"f32"},{"model":"cross-encoder/ms-marco-MiniLM-L6-v2","peak_memory":{"maximum":1560.453125,"mean":886.6770833333334,"minimum":521.984375,"unit":"MB"},"provider":"sentence-transformers","variant":"f32"},{"model":"fixed_bert","peak_memory":{"maximum":205.90625,"mean":205.58854166666666,"minimum":205.328125,"unit":"MB"},"provider":"tokenizers","variant":"built-in"},{"model":"fixed_bpe","peak_memory":{"maximum":206.234375,"mean":205.75,"minimum":205.5,"unit":"MB"},"provider":"tokenizers","variant":"built-in"},{"model":"mirth/chonky_mmbert_small_multilingual_1","peak_memory":{"maximum":635.234375,"mean":623.4427083333334,"minimum":600.0625,"unit":"MB"},"provider":"tokenizers","variant":"f32"},{"model":"antflydb/gliner2-base-v1","peak_memory":{"maximum":1779.546875,"mean":1401.1354166666667,"minimum":1211.796875,"unit":"MB"},"provider":"gliner2","variant":"f32"},{"model":"openai/whisper-tiny","peak_memory":{"maximum":498.125,"mean":394.1822916666667,"minimum":188.6875,"unit":"MB"},"provider":"whisper.cpp","variant":"f32"}]

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
82f9c31a468e82ee7558527f9ed10fcbafbbeba6db244e5c7e1794ab2950c38b
Aggregate
f93b97be93b9ec8ddd72e77e0ff520e0cbe0e7ef7e99b09d11ad2a04e8cc69dd
Provenance
be6735ea10c341fde63f92799e42aefac9f72c7b36b3a3ebaa15ff3f86bd05e0
Harness commit
aa0b314c7390539067212deda68966c70b8b66d3

Scope notes

  • Inference memory follows the benchmark-specific max-of-two-views accounting contract and is not directly interchangeable with database service footprint.
  • 37 of 44 independent model/provider rows produced measurements; the remaining 7 rows stay in the tables as unmeasured values.
  • Charts use one fixed representative model per category; the category tables retain every model and provider row.
  • Reading / OCR has no successful throughput or publishable peak-memory measurement and remains table-only.
Selected partial evidence
Completed
Antfly
v0.2.0 ·
Runtime
13m 41s
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

Inference memory follows the benchmark-specific max-of-two-views accounting contract and is not directly interchangeable with database service footprint.

37 of 44 independent model/provider rows produced measurements; the remaining 7 rows stay in the tables as unmeasured values.

Charts use one fixed representative model per category; the category tables retain every model and provider row.

Reading / OCR has no successful throughput or publishable peak-memory measurement and remains table-only.

Measurement group

Generation

Generation results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
ggml-org/gemma-4-E4B-it-GGUFQ4_0antfly————
google/gemma-4-E4B-it-qat-q4_0-ggufQAT q4_0 + MTP k=2antfly————
unsloth/Qwen3-1.7B-GGUFQ4_K_Mantfly8,555.50.121 pass7,297.5
ggml-org/gemma-4-E4B-it-GGUFQ4_0llama.cpp1,809.90.561 pass7,434.4
ggml-org/gemma-4-E4B-it-GGUFQ4_0ollama995.21.021 pass10,929.0
ggml-org/gemma-4-E4B-it-GGUFQ4_0vllm-metal801.81.261 pass25,524.1
google/gemma-4-E4B-it-qat-q4_0-ggufQAT q4_0llama.cpp1,870.70.561 pass7,605.1
google/gemma-4-E4B-it-qat-q4_0-ggufQAT q4_0ollama913.61.131 pass7,387.3
google/gemma-4-E4B-it-qat-q4_0-ggufQAT q4_0vllm-metal1,082.20.931 pass28,351.2
unsloth/Qwen3-1.7B-GGUFQ4_K_Mllama.cpp897.71.141 pass5,665.3
unsloth/Qwen3-1.7B-GGUFQ4_K_Mollama412.12.551 pass5,162.7
unsloth/Qwen3-1.7B-GGUFQ4_K_Mvllm-metal318.53.161 pass25,832.1

ggml-org/gemma-4-E4B-it-GGUF · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · Q4_0 · 3/4 providers measured · Higher is better

ggml-org/gemma-4-E4B-it-GGUF · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · Q4_0 · 3/4 providers measured · Lower is better

Measurement group

Dense embedding

Dense embedding results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
BAAI/bge-small-en-v1.5f32antfly158.26.870.253 cosine752.8
BAAI/bge-large-en-v1.5f32antfly936.31.110.162 cosine2,904.2
mixedbread-ai/mxbai-embed-large-v1f32antfly967.01.060.226 cosine2,836.5
BAAI/bge-small-en-v1.5f32onnxruntime13.480.000.207 cosine1,024.3
BAAI/bge-small-en-v1.5f32sentence-transformers8.8141.590.207 cosine1,296.8
BAAI/bge-large-en-v1.5f32onnxruntime58.518.560.192 cosine3,448.4
BAAI/bge-large-en-v1.5f32sentence-transformers20.964.920.192 cosine2,297.2
mixedbread-ai/mxbai-embed-large-v1f32onnxruntime58.618.690.271 cosine3,446.9
mixedbread-ai/mxbai-embed-large-v1f32sentence-transformers20.265.970.271 cosine2,633.2

BAAI/bge-small-en-v1.5 · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 3/3 providers measured · Higher is better

BAAI/bge-small-en-v1.5 · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 3/3 providers measured · Lower is better

Measurement group

Sparse embedding

Sparse embedding results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
sparse-encoder-testing/splade-bert-tiny-nq-onnxonnxantfly————
sparse-encoder-testing/splade-bert-tiny-nq-onnxonnxonnxruntime4.4253.38334 entries628.5
sparse-encoder-testing/splade-bert-tiny-nq-onnxonnxsentence-transformers10.5130.63334 entries1,275.5

sparse-encoder-testing/splade-bert-tiny-nq-onnx · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · onnx · 2/3 providers measured · Higher is better

sparse-encoder-testing/splade-bert-tiny-nq-onnx · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · onnx · 2/3 providers measured · Lower is better

Measurement group

Multimodal embedding

Multimodal embedding results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
antflydb/clipclapQ4_Kantfly132.88.710.055 cosine523.5

antflydb/clipclap · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · Q4_K · 1/1 providers measured · Higher is better

antflydb/clipclap · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · Q4_K · 1/1 providers measured · Lower is better

Measurement group

Reranking

Reranking results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
mixedbread-ai/mxbai-rerank-base-v1f32antfly95.711.161 pass1,767.6
cross-encoder/ms-marco-MiniLM-L6-v2f32antfly35.629.201 pass625.2
mixedbread-ai/mxbai-rerank-base-v1f32onnxruntime52.519.391 pass4,766.5
mixedbread-ai/mxbai-rerank-base-v1f32sentence-transformers16.791.241 pass1,827.2
cross-encoder/ms-marco-MiniLM-L6-v2f32onnxruntime10.5102.111 pass960.1
cross-encoder/ms-marco-MiniLM-L6-v2f32sentence-transformers6.8199.591 pass886.7

mixedbread-ai/mxbai-rerank-base-v1 · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 3/3 providers measured · Higher is better

mixedbread-ai/mxbai-rerank-base-v1 · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 3/3 providers measured · Lower is better

Measurement group

Chunking

Chunking results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
fixed_bertbuilt-inantfly5.2200.983 chunks353.3
fixed_bpebuilt-inantfly5.1202.043 chunks402.9
mirth/chonky_mmbert_small_multilingual_1f32antfly5.2202.493 chunks334.2
fixed_bertbuilt-intokenizers0.121,789.553 chunks205.6
fixed_bpebuilt-intokenizers0.123,741.613 chunks205.8
mirth/chonky_mmbert_small_multilingual_1f32tokenizers0.128,908.903 chunks623.4

mirth/chonky_mmbert_small_multilingual_1 · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 2/2 providers measured · Higher is better

mirth/chonky_mmbert_small_multilingual_1 · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 2/2 providers measured · Lower is better

Measurement group

Structured extraction

Structured extraction results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
antflydb/gliner2-base-v1f32antfly158.26.391 recall1,015.4
antflydb/gliner2-base-v1f32gliner229.035.481 recall1,401.1

antflydb/gliner2-base-v1 · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 2/2 providers measured · Higher is better

antflydb/gliner2-base-v1 · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 2/2 providers measured · Lower is better

Measurement group

Reading / OCR

Reading / OCR results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
antflydb/Florence-2-basef32antfly——0 word recall—
antflydb/Florence-2-basef32transformers——0 word recall—

Measurement group

Transcription

Transcription results

Antfly v0.2.0 · 56a1b1a5

ModelVariantProviderp95 msThroughput ops/sQualityPeak memory MB
openai/whisper-tinyf32antfly——0.400 word recall—
openai/whisper-tinyf32faster-whisper——0.600 word recall—
openai/whisper-tinyf32whisper.cpp124.08.610.800 word recall394.2

openai/whisper-tiny · Throughput

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 1/3 providers measured · Higher is better

openai/whisper-tiny · Peak memory

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · f32 · 1/3 providers measured · Lower is better

III

1 of 3 lanes measured

CRAG

Retrieval, ranking, and evaluation lanes over the CRAG corpus and query set.

i

fulltext-crag-footprint

complete

Full-text search

Matched-quality full-text retrieval across increasing CRAG corpus sizes, with query behavior, swap-backed serving demand, and complete post-stop database volume.

Methodology scope · protocol · interpretation

CRAG full-text search

Scope

This lane compares Antfly, Elasticsearch, and Quickwit as full-text retrieval services over the same CRAG Task 1/2 corpus and query sample. At 2,000, 5,000, 9,000, and 13,530 documents it measures cache-excluded working set, cache-inclusive memory, final complete database volume, query p95, QPS, and normalized gold-answer evidence in the top one and top five results.

The main report repeats the honed publication charts for working set, final database volume, and query p95 by corpus size. The tables retain QPS and quality beside those plots. This is a full-text search comparison, not merely a footprint measurement.

Publication protocol

  • Run every engine in a Linux cgroup v2 container on the shared Circus Linux/arm64 lane.
  • Use the same immutable CRAG corpus and query set for all engines.
  • Give Elasticsearch a fixed 1 GiB heap and record that setting.
  • Run three fresh alternating lifecycles, rather than reusing an index or container between repetitions.
  • For each lifecycle, run one deterministic 200-query sample at concurrency 1 after ten warmup queries; require zero query errors.
  • Use product-default full-text analyzers and resolve returned IDs through the same canonical CRAG document map before calculating top-one and top-five gold-answer evidence.
  • Treat sampled cgroup memory.current as cache-inclusive memory and anon + shmem as the cache-excluded working-set comparison.
  • Give every engine one newly created, run-labeled Docker local volume at its complete persistence root: /data, /usr/share/elasticsearch/data, or /quickwit/qwdata. The same digest-pinned Alpine probe measures each whole volume on the shared Linux Docker engine; APFS bind mounts are ineligible.
  • Give every engine the same fixed 30-second post-workload persistence window, then capture allocated and apparent integer bytes once at post_workload. Also capture once at empty and ready, then at the post-stop final barrier. empty permits root directory-block overhead but no entries. Verify graceful stop before the headline final capture; neither the delay nor qualification depends on an engine’s observed bytes.
  • Publish final allocated bytes as the arithmetic mean, every value, and the full range of the three independent construction lifecycles. Retain apparent bytes, lifecycle samples, per-volume manifests, and engine index APIs only as diagnostics. The legacy index_disk_mb field is not comparable.
  • Require storage.json and its validation receipt, which ties the measurement to the sampler hash, probe digest, declared scope, lifecycle barriers, environment identity, and fresh or materialized cell sums.
  • Require the quiet-host gate for latency publication. Memory and storage remain valid only when all engine cells passed their lifecycle and cgroup checks.

The v0.2.0 honed page describes the host as Linux/aarch64 containers under Docker Desktop on Apple Silicon. It does not describe this as bare-metal Linux.

Run evidence parameters · variation · provenance

Benchmark parameters

{"document_counts":[2000,5000,9000,13530],"trial_count":3}

Trial variation

[{"document_count":2000,"engine":"antfly","ranges":{"demand_working_set":{"maximum":184.172544,"mean":159.4245,"minimum":158.113792,"unit":"MB"},"final_database_volume":{"maximum":31.96928,"mean":30.609408,"minimum":29.908992,"unit":"MB"},"query_p95":{"maximum":0.9867,"mean":0.8418,"minimum":0.8214,"unit":"ms"}}},{"document_count":5000,"engine":"antfly","ranges":{"demand_working_set":{"maximum":258.43712,"mean":214.7246,"minimum":210.898944,"unit":"MB"},"final_database_volume":{"maximum":70.017024,"mean":70.014293,"minimum":70.012928,"unit":"MB"},"query_p95":{"maximum":1.072,"mean":1.0608,"minimum":1.011,"unit":"ms"}}},{"document_count":9000,"engine":"antfly","ranges":{"demand_working_set":{"maximum":324.005888,"mean":306.9174,"minimum":290.799616,"unit":"MB"},"final_database_volume":{"maximum":127.11936,"mean":127.056555,"minimum":127.025152,"unit":"MB"},"query_p95":{"maximum":1.1726,"mean":1.1433,"minimum":1.0736,"unit":"ms"}}},{"document_count":13530,"engine":"antfly","ranges":{"demand_working_set":{"maximum":439.287808,"mean":401.4653,"minimum":376.369152,"unit":"MB"},"final_database_volume":{"maximum":188.481536,"mean":188.481536,"minimum":188.481536,"unit":"MB"},"query_p95":{"maximum":1.3414,"mean":1.312,"minimum":1.2871,"unit":"ms"}}},{"document_count":2000,"engine":"elasticsearch","ranges":{"demand_working_set":{"maximum":1572.61824,"mean":1539.8175,"minimum":1538.88768,"unit":"MB"},"final_database_volume":{"maximum":28.213248,"mean":28.194133,"minimum":28.176384,"unit":"MB"},"query_p95":{"maximum":3.0325,"mean":2.9416,"minimum":2.8883,"unit":"ms"}}},{"document_count":2000,"engine":"quickwit","ranges":{"demand_working_set":{"maximum":332.013568,"mean":327.3441,"minimum":319.52896,"unit":"MB"},"final_database_volume":{"maximum":62.17728,"mean":62.17728,"minimum":62.17728,"unit":"MB"},"query_p95":{"maximum":2.3361,"mean":2.2917,"minimum":2.2346,"unit":"ms"}}},{"document_count":5000,"engine":"elasticsearch","ranges":{"demand_working_set":{"maximum":1576.349696,"mean":1571.9424,"minimum":1563.181056,"unit":"MB"},"final_database_volume":{"maximum":68.071424,"mean":68.060501,"minimum":68.05504,"unit":"MB"},"query_p95":{"maximum":3.2241,"mean":3.0764,"minimum":2.7218,"unit":"ms"}}},{"document_count":5000,"engine":"quickwit","ranges":{"demand_working_set":{"maximum":413.569024,"mean":409.559,"minimum":406.224896,"unit":"MB"},"final_database_volume":{"maximum":153.464832,"mean":153.464832,"minimum":153.464832,"unit":"MB"},"query_p95":{"maximum":2.7762,"mean":2.6855,"minimum":2.6546,"unit":"ms"}}},{"document_count":9000,"engine":"elasticsearch","ranges":{"demand_working_set":{"maximum":1639.46496,"mean":1613.6151,"minimum":1596.166144,"unit":"MB"},"final_database_volume":{"maximum":121.38496,"mean":121.374037,"minimum":121.368576,"unit":"MB"},"query_p95":{"maximum":3.202,"mean":3.1196,"minimum":3.0971,"unit":"ms"}}},{"document_count":9000,"engine":"quickwit","ranges":{"demand_working_set":{"maximum":570.105856,"mean":565.9402,"minimum":561.577984,"unit":"MB"},"final_database_volume":{"maximum":140.92288,"mean":140.92288,"minimum":140.92288,"unit":"MB"},"query_p95":{"maximum":3.0926,"mean":2.9771,"minimum":2.9173,"unit":"ms"}}},{"document_count":13530,"engine":"elasticsearch","ranges":{"demand_working_set":{"maximum":1646.096384,"mean":1635.1273,"minimum":1611.763712,"unit":"MB"},"final_database_volume":{"maximum":181.460992,"mean":181.455531,"minimum":181.444608,"unit":"MB"},"query_p95":{"maximum":3.525,"mean":3.1883,"minimum":3.138,"unit":"ms"}}},{"document_count":13530,"engine":"quickwit","ranges":{"demand_working_set":{"maximum":685.748224,"mean":685.6253,"minimum":671.8464,"unit":"MB"},"final_database_volume":{"maximum":278.642688,"mean":278.642688,"minimum":278.642688,"unit":"MB"},"query_p95":{"maximum":3.8247,"mean":3.8052,"minimum":3.5119,"unit":"ms"}}}]

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
88bfae279bf9c6b7a692515fea767f08453dd0d7177c0cd329fa4996fe0a5c34
Aggregate
d0b666d0adf7f39c2f78881f851563a286d23652a3e8018570eea84b84fc20b7
Provenance
9576f031a39a2ec8091ebc29bbff68750f34f34cd27adc7734524b68da5d0b22
Harness commit
a379ba64c66bfa7f2468d1fcfc78d3e79a32f639

Scope notes

  • Each engine and corpus cell uses three fresh lifecycles; Antfly storage aggregates marked provisional retained stable final post-stop observations after the post-workload stabilization window timed out.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
Elapsed time not captured
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

Each engine and corpus cell uses three fresh lifecycles; Antfly storage aggregates marked provisional retained stable final post-stop observations after the post-workload stabilization window timed out.

Query p95

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 2,000–13,530 documents · 3 trials · Lower is better

Demand working set

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 2,000–13,530 documents · 3 trials · Lower is better

Final database volume

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · 2,000–13,530 documents · 3 trials · Lower is better

Resource footprint

Antfly v0.2.0 · 56a1b1a5

EngineDocumentsDemand working set MBFinal database volume MBTrials
antfly2,000159.4 MB30.6 MB3
antfly5,000214.7 MB70.0 MB3
antfly9,000306.9 MB127.1 MB3
antfly13,530401.5 MB188.5 MB3
elasticsearch2,0001,539.8 MB28.2 MB3
quickwit2,000327.3 MB62.2 MB3
elasticsearch5,0001,571.9 MB68.1 MB3
quickwit5,000409.6 MB153.5 MB3
elasticsearch9,0001,613.6 MB121.4 MB3
quickwit9,000565.9 MB140.9 MB3
elasticsearch13,5301,635.1 MB181.5 MB3
quickwit13,530685.6 MB278.6 MB3

Query behavior and ranking quality

Antfly v0.2.0 · 56a1b1a5

EngineDocumentsQPSp95 msTop-1Top-5
antfly2,0001,456.50.840.2200.295
antfly5,0001,254.31.060.2300.290
antfly9,0001,286.91.140.2300.285
antfly13,5301,121.21.310.2350.290
elasticsearch2,000502.72.940.2000.285
quickwit2,000530.22.290.2150.290
elasticsearch5,000494.83.080.2100.280
quickwit5,000454.92.690.2150.295
elasticsearch9,000489.43.120.2100.285
quickwit9,000396.52.980.2200.295
elasticsearch13,530471.93.190.2150.280
quickwit13,530323.23.810.2200.295
ii

rag-crag

missing

Dense retrieval diagnostic

Controlled dense-retrieval diagnostics over the CRAG corpus and query set.

Methodology scope · protocol · interpretation

CRAG dense retrieval diagnostic

What this lane measures

This is a retrieval-only diagnostic over the official CRAG Task 1/2 v4 development data. It compares how six vector databases retrieve answer-bearing passages from the same corpus. It is not an official CRAG Task 1/2 score: it stops before answer generation and does not run the official CRAG judge.

Upstream CRAG evaluates generated answers to questions whose relevant context may change over time. The full upstream workflow supplies retrieved context to an answer model and evaluates the answer. This Circus lane uses CRAG only as a fixed real-world question and web-page source so that database retrieval can be measured separately from model quality, provider latency, and judge behavior.

Retrieval protocol

  • Dataset: official Task 1/2 v4 development split, 2,706 questions and 13,530 provided web-result pages.
  • Dataset SHA-256: afa29f2b3facfb5d15aa9cded00d5ec90ff76f3e67279e7b99cfe86659a641ca.
  • Documents: normalize each source page, cap it at 20,000 characters, then form deterministic 384-token passages with 64-token overlap.
  • Embeddings: normalized 384-dimensional BAAI/bge-small-en-v1.5 vectors, computed once and loaded unchanged into every engine.
  • Search: identical query vectors, fixed query order, cosine distance, and the top five complete passages.
  • Engines: Antfly, Milvus, Chroma, pgvector, Weaviate, and Elasticsearch.
  • Evidence: service version, image identity, effective index settings, subject version and SHA-256, and per-query retrieval rows are retained before the aggregate is accepted.

The gauntlet adds retrieval-only lexical, hybrid, and local agentic/KG rows. Those rows are diagnostics, not substitutes for the six-engine dense cohort. Paid answer generation and judging require the separately guarded full CRAG command and are not part of this Circus benchmark lane.

Metrics and publication status

The harness records retrieval latency and whether any normalized gold-answer string appears in the top-one or top-five retrieved context. These are local retrieval sanity metrics, not the official CRAG judge score.

This lane is excluded from the honed publication profile. Its current adapters use unequal client transports: Antfly and Elasticsearch open a new HTTP connection and serialize JSON inside each timed request, while other engines use persistent native clients. The ANN settings also were not calibrated to a common recall floor. Those differences confound both latency and hit-at-five rankings, so the Circus profile retains the lane only as a diagnostic and must not present a cross-engine leaderboard from it.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
iii

ragas-crag-eval

missing

RAGAS evaluation

RAG answer and retrieval quality measured with the RAGAS evaluation surface.

Methodology scope · protocol · interpretation

RAGAS CRAG Evaluation Methodology

Scope

This benchmark evaluates the CRAG RAG artifacts generated by the rag-crag benchmark entry. It does not run a separate retrieval stack; it consumes the saved CRAG retrieval and answer JSONL files so the RAGAS row describes the same RAG behavior shown in the CRAG table.

Current Metrics

The initial adapter reports RAGAS-shaped proxy metrics from CRAG artifacts:

  • context_recall_proxy: whether the gold answer appears in top-k context
  • context_precision_proxy: whether the gold answer appears in top-one context
  • answer_correctness_proxy: whether the generated answer contains the gold answer
  • missing_rate: how often the answer generator returned no answer or unknown

If the ragas Python package is installed, the adapter records that fact, but the current row still uses CRAG artifact proxies. A follow-up should add the true RAGAS metric calls after the exact LLM and embedding provider choices are settled.

Inputs

  • Retrieval artifacts: rag-crag/*-retrieval.jsonl
  • Answer artifacts: rag-crag/*-answers.jsonl
  • Summary files: rag-crag/retrieval-summary.json and rag-crag/answer-summary.json

The row is provisional until true RAGAS package metrics are enabled.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
IV

deployment-artifacts

complete

Deployment artifacts

Release artifact metadata for the binaries and peer images used by the selected benchmark runs.

Methodology scope · protocol · interpretation

Deployment artifacts

This lane establishes packaging and transfer facts for the exact Linux/arm64 artifacts represented by the honed benchmark review. It does not start a database, measure runtime resource use, or assign a composite score.

Cohort and identity

The cohort is Antfly plus the five peers in the honed VectorDBBench publication matrix: Weaviate, pgvector, Chroma, Milvus, and Elasticsearch. Antfly is bound to the honed subject manifest. Each peer is bound to the exact digest-pinned image reference declared by this lane; the lane uses the same image environment overrides as VectorDBBench.

Every engine/artifact pair is one portable publication-cache cell. A cache hit requires the same subject release archive identity or peer image reference, platform, collector protocol, and workload identity. Cache objects retain normalized facts, source metadata, logs, and a lifecycle receipt. Cache identity excludes timing because the lane performs no timed work.

Download payload

Antfly’s download payload is the byte size of the official Linux/arm64 release archive from the GitHub Releases API. The collector requires the API asset digest to match the archive SHA-256 in the honed subject manifest. It separately retains the executable byte size, executable SHA-256, and static-linkage identification from that subject manifest.

A peer’s download payload is the sum of the compressed layer sizes in the one os=linux, architecture=arm64 child selected from docker manifest inspect --verbose. The collector retains the configured index reference, resolved child digest, selected descriptor, config digest, layer count, and selected manifest. Missing or ambiguous platform selection fails the lane.

The image total sums every compressed layer in the selected manifest without credit for layers already cached on an operator’s machine. A machine with shared layers may therefore transfer less. Registry transfer overhead and expanded filesystem size are excluded. This is a reproducible artifact comparison, not an estimate of every installation path.

Deployment vocabulary

“Separately managed prerequisites” means software an operator must install, launch, upgrade, and coordinate separately from the displayed server artifact. None excludes operating-system kernel, storage, and networking. Peer container rows therefore name an OCI-compatible container runtime. Components packaged inside an image, such as Elasticsearch’s JVM or Milvus’s embedded etcd/local-storage topology, are bundle components rather than separately managed prerequisites.

The compact review table describes only the exact artifacts used by the publication matrix. It does not claim that these are the only installation forms supported by each project.

Run evidence parameters · variation · provenance

Benchmark parameters

{"result_rows":6}

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
fa06a2c71cd188ed8953a8d9325847745a57b552ab79a638d3da2d4709e59333
Aggregate
ec83559ce4496224ff43cc565922e704565e7957ef82bdace74f88af5d8c22c7
Provenance
ac53ced0d4c4be9a998bb0435f3aea06359d354d58f041b622290a13ce056af9
Harness commit
44896e06d10f118a245e9939ee1dcda50afc8fad

Scope notes

  • Artifact metadata describes deployment inputs; it is not a performance benchmark.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
22s
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

Artifact metadata describes deployment inputs; it is not a performance benchmark.

Result summary

Antfly v0.2.0 · 56a1b1a5

EngineStatus
antflyok
weaviateok
pgvectorok
chromaok
milvusok
elasticsearchok
V

agent-effort-quickstart

complete

Agent access effort

End-to-end agent activation and grounded retrieval effort for grep, Antfly, Chroma, and Milvus Lite.

Methodology scope · protocol · interpretation

Agent Access Effort

Question

Given a raw corpus and a named access system, how much agent work is required to make the corpus usable and complete grounded retrieval tasks?

This is an end-to-end product-choice benchmark. Grep is a first-class subject, not merely an engine-quality baseline: it has almost no activation cost and is how coding agents commonly search local data. Antfly, Chroma, and Milvus must earn their indexing and setup cost through easier or more effective retrieval.

Clean pilot protocol

The checked result is the one-trial-per-system clean-20260821 internal pilot. A fresh pi session using openrouter/deepseek/deepseek-v4-flash ran each subject sequentially:

  • grep (ripgrep from the Debian bookworm image),
  • Antfly v0.2.0, commit 56a1b1a591f5db0b80017e425ad0c449f52f38fe,
  • Chroma 1.5.9,
  • Pymilvus 3.0.0 with Milvus Lite 3.0.

Each task image contained 240 synthetic JSONL documents. Eight documents held fictional facts; 232 deterministic distractors shared vocabulary but not the answer-bearing entities. Every document also carried a precomputed 256-dimensional deterministic token-hash vector. This avoids model-download and embedding-runtime differences in the activation measurement. The questions, answers, and evidence document IDs are fixed by the harness.

Software was preinstalled but not configured. Environment image builds and software installation were excluded. The agent received one concise subject usage guide, the raw corpus, and helper commands for producing compatible query vectors and recording milestones.

Trial sequence

  1. Configure the assigned system and load/index all 240 documents.
  2. Verify its retrieval surface is usable. Queries while an index is still building do not qualify.
  3. Record the ready milestone.
  4. Reveal the eight questions only after readiness.
  5. Retrieve each answer through the assigned system and record the answer plus its evidence document ID.

After a database subject records readiness, the harness removes the raw corpus. This prevents the question-answering phase from silently falling back to grep. The grep row retains the corpus because the file is its retrieval surface.

The verifier requires:

  • all eight exact answers,
  • all eight expected evidence document IDs,
  • a ready marker before every grounded milestone,
  • the expected live or persistent system artifact,
  • no post-readiness raw-corpus access for database rows.

The clean pilot did not independently execute a subject-specific readiness probe at the instant of the marker. Trajectory review found that Milvus marked ready while its collection was released; its first post-ready query failed and the agent loaded the collection afterward. The Milvus ready time is therefore invalid and is not published.

Metrics

  • Ready seconds: agent-start to the ready marker, retained only when the trajectory shows the assigned retrieval surface was usable at that point.
  • All grounded seconds: agent-start to completion of all eight grounded answers. Agents recorded the answers as a batch in this pilot, so this is a panel-completion metric, not steady-state per-query latency.
  • Work tool calls: pi tool calls excluding direct effort-mark and effort-questions bookkeeping calls.
  • Failure-bearing calls: calls whose tool result was an error or whose retained output contained a concrete traceback, HTTP/API failure, invalid vector dimensions, or failed command. This catches curl pipelines that returned exit zero despite an API failure.
  • Gross tokens: ordinary input, cache-read input, and output tokens summed.
  • Agent cost: Harbor/pi provider accounting.
  • Success rate: grounded answers divided by eight; correctness is a bar.

Checked result

SystemValid readyAll 8 groundedWork tool callsFailure-bearing callsGross tokensAgent cost
grep16.3 s42.6 s180152,279$0.0046
Chroma35.2 s65.3 s180168,956$0.0066
Milvus Liteinvalid127.9 s337328,205$0.0064
Antfly211.9 s272.7 s5361,581,093$0.0248

All four rows grounded 8/8 answers. Milvus violated the readiness protocol. On this small exact-entity workload, grep completed the grounded panel fastest; no indexed subject recovered its activation cost.

Trajectory audit

Raw tool-call totals were 28 grep, 28 Chroma, 35 Milvus, and 63 Antfly, but they are not directly comparable. Grep, Chroma, and Antfly each spent ten separate calls on benchmark markers; the Milvus agent invoked its eight grounded markers from inside one generated Python script. The checked table therefore reports direct work calls after removing only explicit marker calls.

Antfly used 43 calls before its ready marker. Its first table, external-vector index, and batch load were substantially complete by call 13. A malformed manual vector probe then returned InvalidVectorDimensions; the agent misdiagnosed that query error as broken ingestion, restarted Antfly, reloaded without the vector index, investigated zero coverage, and finally dropped/recreated/reloaded the table in the correct order. That diagnostic spiral accounts for most of the 211.9-second activation time.

Antfly also emitted a 42,783-character unprojected index-status response early in the session. Replaying that result through the remaining turns contributed to 1.45 million cache-read tokens. Gross traffic is intentionally retained, but uncached input was 122,875 tokens; the gross-token ratio should not be read as an equivalent billing ratio.

The one-page subject guides were not equally executable. Chroma received a working client/collection snippet and had no failure-bearing call. Milvus received prose describing the desired schema, then spent ten introspection calls reconciling post-training Pymilvus 3.0 schema and index APIs. The Antfly guide incorrectly instructed the agent to create a redundant full-text index even though v0.2.0 created full_text_index_v0 with the table; that caused one of its six failure-bearing calls.

Finally, the exact-entity questions were answered through Antfly full-text search, while the task still required Antfly’s vector index to be ready. The vector setup was therefore pure activation tax in this workload. A successor should either let each system choose the minimum sufficient retrieval path or separate exact and semantic panels.

Scope and interpretation

This is intentionally an internal pilot, not a honed publication result:

  • one trial per system,
  • one agent/model,
  • small synthetic corpus,
  • exact entity anchors favor grep,
  • deterministic hash vectors rather than a production embedding model,
  • software acquisition and live website UX excluded,
  • no memory, storage, or backend request-latency claim.

The result validates the benchmark shape and exposes onboarding friction. It does not estimate model variance or the query-count break-even point. A later campaign can reuse the same phase boundaries on larger semantic and long-document corpora without expanding this pilot’s claims.

Reproduction and retained evidence

  • Harness: benchmarks/agent-access-effort-harness/access_effort.py
  • Checked aggregate: benchmarks/agent-access-effort-harness/result.json
  • Deterministic contract: make agent-access-effort-smoke
  • Paid run: make agent-access-effort-run AAE_RUN_ID=<id>
  • Reprojection: make agent-access-effort-report AAE_RUN_ID=<id>

Raw Harbor trajectories remain local under results/agent-access-effort/<run-id>/jobs/; they are excluded from the site snapshot because they contain large model transcripts and task data.

Run evidence parameters · variation · provenance

Benchmark parameters

{"result_rows":4}

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
e2ff2133c13b55f60b080aa7a37ef41d575a44144482c85415c98ace9ecf01b2
Aggregate
f6082996bae217f899bd77f8316af8544d5fe3578157d65ba4810f4245e9435d
Provenance
fdd85399dfdc6529020b385940c29077d99c68bffaa217eb29e9b1e3501bd772
Harness commit
96db7cdd5f0e6743c4c6b86d4af7c85e43502a8d

Scope notes

  • Internal one-trial pilot on a 240-document synthetic exact-entity workload; software installation, live website UX, and model variance are out of scope.
  • Milvus grounded 8/8 but violated the readiness protocol; its ready time is not published. Work tool calls exclude direct benchmark marker calls.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
0s
Platform
darwin · arm64
Machine
Apple M5 Pro · 15 CPU · 51.5 GB
Build
optimization mode not captured · Zig compiler version not captured

Internal one-trial pilot on a 240-document synthetic exact-entity workload; software installation, live website UX, and model variance are out of scope.

Milvus grounded 8/8 but violated the readiness protocol; its ready time is not published. Work tool calls exclude direct benchmark marker calls.

Result summary

Antfly v0.2.0 · 56a1b1a5

SystemGroundedReady sAll grounded sWork tool callsFailure-bearing callsGross tokensAgent cost USDStatus
grep116.3 s42.6 s180152,2790.005 USDpassed
antfly1211.9 s272.7 s5361,581,0930.025 USDpassed
chroma135.2 s65.3 s180168,9560.007 USDpassed
milvus1—127.9 s337328,2050.006 USDreadiness protocol violation
VI

graph-benchmark

complete

Graph

Graph query performance, Pokec-small cross-engine diagnostics, official LSQB capability, and bounded SNB Interactive qualification.

Methodology scope · protocol · interpretation

Graph Database Benchmark v2 Methodology

Scope and provenance

This benchmark has two lanes and does not calculate a composite winner. LSQB-derived is an Antfly-owned anchored microbenchmark over LSQB data. The Pokec suite is a clean-room implementation informed by the public categories and workload ratios described by Memgraph’s Benchgraph material. It reuses the public Pokec import files, not Benchgraph implementation code. Neither lane is an audited LDBC result.

The scorecard keeps these measurements separate:

LaneScorecard metricsDirection
LSQB-derived F2warm serial p50, warm serial p99latency lower
Pokec W1completed QPS, peak process RSSQPS higher; RSS lower

Full statistics, errors, run ranges, and raw samples remain mandatory even when the scorecard is used.

Engines and equal client work

The comparison is Antfly, Neo4j 5.26.29, and Memgraph 3.12.0. Kuzu is excluded because it is not exercised through a comparable network service. Every timed throughput cell uses the same Go executable, deterministic schedule, quantile implementation, response-consumption rule, worker count, and wall-clock. Antfly is accessed over persistent HTTP/1.1; both peers use the same official Neo4j Go Bolt driver. Transport is part of observed client latency and is reported, not hidden.

Only equivalent User(id) and benchmark-namespace ID indexes are created. There is no engine-specific query tuning. Each run starts from a fresh database and performs complete correctness checks before timing. Mutating cells use a reserved BenchUser namespace so source reads cannot change; that namespace is restored to its 1,024-node ring baseline after every mutating cell. Timed requests are never retried. Errors are retained and exclude a run from the publication gate.

LSQB-derived lane

The pinned source, data loading, parameter selection, BLAKE3 result oracle, and N1/P2/F2 definitions are specified in graph-lsqb-derived.md. The public LSQB-derived metric is warmed serial latency for this exact endpoint-filtered lookup, returning matching Post IDs:

(Forum)-[:CONTAINER_OF]->(Post)-[:HAS_TAG]->(Tag {id: $tag_id})

Unfiltered P2 C12 throughput remains a retained diagnostic. It is not part of the graph scorecard or public filtered-lookup claim. Default, medium, and full use LSQB SF0.003, SF0.1, and SF1 respectively.

Pokec data and parameter oracle

Profiles use the public Memgraph Pokec import files:

ProfileDatasetUsersDirected FRIEND edgesAnchors
quickPokec-small10,000121,71612
mediumPokec-medium100,0001,768,51548
fullPokec-large1,632,80330,622,564128

The harness records the downloaded source SHA-256 and refuses unexpected node or edge counts. Anchors are selected deterministically across out-degree deciles with seed 0xB37C4. Every selected anchor must return its complete result below 900 rows through four hops; this stays below rc18’s 1,000 pattern match ceiling rather than comparing truncated results.

Expansion semantics are one endpoint result per directed walk. Antfly uses a chain of fixed one-hop pattern steps. Cypher uses one fixed MATCH clause per hop, avoiding vendor differences in variable-length path uniqueness. The offline SQLite oracle stores the exact result count and canonical BLAKE3 digest including multiplicity for every parameter. Aggregates and shortest path have exact scalar oracles. All 101 quick-profile checks per engine/run must pass before timing. Writes are executed and verified in the isolated benchmark namespace.

Pokec operations

IDOperation
R1exact indexed node lookup
WNinsert a new benchmark node
U1increment one benchmark-node property
WEinsert one directed benchmark edge
AG1age buckets and counts
AG2age count/min/max/sum/average
E1–E4exact fixed 1-, 2-, 3-, or 4-hop directed expansion
E2Fexact 2-hop expansion with endpoint age >= 18
N2concatenated exact 1-hop and exact 2-hop neighborhood
SPdirected unweighted shortest path, maximum depth 8

Every operation has an unwarmed serial observation and a prewarmed serial distribution. Isolated throughput uses 12 clients. Each non-mutating operation also receives a 70% operation / 30% write cell, split evenly between node and edge insert. The deterministic realistic workloads are:

  • W1: 20% analytical, 40% point read, 10% update, 30% write;
  • W2: 70% point read, 30% write;
  • W3: 50% point read, 50% write;
  • W4: 30% point read, 70% write.

The quick profile uses one-second isolated/mixed cells and two-second W1–W4 cells. Medium uses 5/10 seconds; full uses 15/30 seconds. Warmup is untimed. Every successful timed request is retained in JSONL. Reports contain completed QPS, error counts, p50/p95/p99, per-operation statistics, and peak PID RSS.

Persistent database volume

The honed LSQB SF0.1 F2 lane creates a new, run-labeled Docker local volume for every engine and repetition. Only the complete writable database root is measured (/data for Antfly and Neo4j, /var/lib/memgraph for Memgraph); read-only dataset/tool volumes and client scratch are excluded. A digest-pinned Alpine probe captures whole-volume allocated and apparent bytes once at empty, service-ready-before-ingestion, and post-workload, then at the verified post-stop final barrier. Final allocated bytes are the headline.

All three storage values, their arithmetic mean and range, apparent-byte diagnostics, barrier samples, volume manifests, and lifecycle receipts are retained. A provisional stop timeout remains visible but cannot support a comparative ratio.

Runs, ordering, and reporting

Each profile requires three clean process runs. Engine order rotates by run and uses a different rotation between lanes. Public serial point estimates are the medians of the three run-level p50, p95, and p99 values. Every result row also retains the three run-level percentile records, their min–max ranges, pooled sample percentiles as diagnostics, and all raw samples. Load/index readiness is diagnostic and is never included in query metrics.

summary.json is the machine-readable source of truth. The Markdown report contains the full cell table; scorecard.svg is only the compact two-panel view. There is deliberately no geometric mean or composite rank.

The honed LSQB SF0.1 F2 lane caches only the complete three-engine cohort. Promotion requires Antfly, Neo4j, and Memgraph to each retain three fresh database constructions and process runs, 15,000 timed samples, all three run-level percentile records and ranges, three complete storage receipts and their allocated-byte mean/range, 1,000/1,000 correctness, a valid canonical receipt, and the quiet-host record. The cache identity binds the Antfly subject, both peer image digests, the Linux client and storage-probe image, dataset manifest, harness sources, and protocol. A hit materializes the entire cohort; per-engine cache mixing is not permitted.

Internal fresh-service F2 readiness and convergence

The honed and Circus profiles retain a fresh-service diagnostic that measures how quickly a preloaded graph service becomes useful and settles into its warm filtered-two-hop behavior. It is graph-specific: readiness is followed immediately by the same exact LSQB SF0.1 F2 request used by the warm latency lane. It is not a general process-startup or system-wide Antfly claim.

This cohort is deliberately internal. It is attached to the canonical graph run report and structured result, but the public benchmark-page renderer does not render its table. It is never eligible for the honed publication cache: each honed or gauntlet graph invocation collects it afresh with make graph-f2-warmup-run. The retained diagnostic contract requires:

  • the same Antfly binary, pinned Neo4j and Memgraph images, official LSQB SF0.1 dataset, and Linux/arm64 Docker environment as the primary graph lane;
  • a recorded physical-host state, including whether the honed quiet-host assertion was active, without treating a diagnostic run as publication data;
  • one database construction followed by five fresh service lifecycles per engine, with balanced engine ordering;
  • restart-to-ready measured from immediately before service launch through the first successful engine-native probe: Antfly GET /readyz, Neo4j cypher-shell RETURN 1 plus the pinned-version check, and Memgraph autocommit SHOW VERSION over Bolt;
  • the first F2 latency and first-100 p50/p95 from a fixed 100-anchor panel selected by SHA-256 rank independently of result cardinality;
  • convergence at the first point where three consecutive adjacent 100-query window p50 changes are each within 5%, with a 10,000-query ceiling;
  • steady-state p50/p95 from five deterministic sweeps over all 1,000 anchors after convergence;
  • every timed result checked against the independent count+BLAKE3 oracle, with all 1,000 anchors covered in every engine/lifecycle; and
  • median-of-five run metrics with complete run ranges, raw timestamped samples, lifecycle logs, host evidence, exact schedules, and a canonical receipt.

These seven values are an indivisible internal reporting family: restart-to-ready, first-query, first-100 p50, first-100 p95, queries-to-stable-p50, steady p50, and steady p95. The retained report must show all seven for all three engines; it must not headline convergence while omitting the steady-state latency guardrail or Memgraph.

Qualification and publication

The default command is a small, complete optimization loop with a target wall time below 15 minutes. Medium and full are explicit diagnostic commands. A mixed native-macOS/container run is qualification-only because its process RSS views are not comparable across engines.

The release-facing honed F2 lane is a separate, environment-qualified publication protocol. Antfly, Neo4j, and Memgraph all run sequentially inside the same Docker Desktop Linux/arm64 VM on an explicitly quiescent Apple Silicon host. The published claim must name that environment and is limited to warm serial filtered two-hop latency; it is not a bare-metal Linux result or a claim about general graph-database performance. Publication requires:

  • the exact v0.2.0 Linux/arm64 binary and expected SHA-256;
  • the pinned Neo4j 5.26.29, Memgraph 3.12.0, and Linux client image digests;
  • official LSQB SF0.1 with 432,235 nodes and 1,827,523 relationships;
  • three fresh database constructions and process runs per engine, each on a newly created labeled database volume;
  • five warmed serial sweeps per run over 1,000 deterministic anchors;
  • 1,000/1,000 count+BLAKE3 correctness in every engine/run and zero timed errors;
  • median run-level p50/p95/p99 with all run ranges, pooled diagnostics, raw samples, lifecycle logs, and the physical-host record retained; and
  • a canonical receipt for the indivisible three-engine cohort.

The broader graph-v2/Pokec publication gate remains native-Linux-only and is not satisfied by this bounded F2 artifact.

Run evidence parameters · variation · provenance

Benchmark parameters

{"query_ids":["F2"],"runs":3,"samples_per_engine":15000}

Trial variation

[{"engine":"antfly","ranges":{"final_database_volume":{"maximum":180.453376,"mean":179.746133,"minimum":179.392512,"unit":"MB"},"query_p95":{"maximum":2.7908146000000005,"mean":2.764691650000001,"minimum":2.5298122000000003,"unit":"ms"}}},{"engine":"memgraph","ranges":{"final_database_volume":{"maximum":311.906304,"mean":311.906304,"minimum":311.906304,"unit":"MB"},"query_p95":{"maximum":0.14466905,"mean":0.1440441,"minimum":0.14354615,"unit":"ms"}}},{"engine":"neo4j","ranges":{"final_database_volume":{"maximum":635.670528,"mean":635.663701,"minimum":635.650048,"unit":"MB"},"query_p95":{"maximum":0.6908785500000003,"mean":0.6795417000000001,"minimum":0.6769125000000001,"unit":"ms"}}}]

Peer versions

  • memgraph3.12.0
  • neo4j5.26.29

Evidence digests

Receipt
20c344de0783c3ac97b8d425b0bc34dda2ddb3402918605bc0999ac05e887cc4
Aggregate
901937486ddb63165876bae43241bed6328717deebcccb9f1de121745fc4df2b
Provenance
865d8a5ce1088cd8451ae7c9db34bb2d1506dfab0acf1fa9d12074dd922ea939
Harness commit
44896e06d10f118a245e9939ee1dcda50afc8fad

Scope notes

  • This is the focused F2 SF0.1 cohort, not the full LSQB query suite.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
28m 8s
Platform
darwin · arm64
Machine
Apple M4 Max · 14 CPU · 38.7 GB
Build
optimization mode not captured · Zig compiler version not captured

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

This is the focused F2 SF0.1 cohort, not the full LSQB query suite.

Query p95

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · F2 · 3 trials · Lower is better

Final database volume

Antfly v0.2.0 (56a1b1a5) · darwin-arm64 · Apple M4 Max · F2 · 3 trials · Lower is better

Latency, resources, and served samples

Antfly v0.2.0 · 56a1b1a5

EngineVersionQueryp50 msp95 msp99 msDemand working set MBFinal database volume MBServed samples
antflyantfly 0.2.0 (zig runtime)F20.8322.7655.716Not recorded MB179.7 MB15,000
memgraph3.12.0F20.1130.1440.175Not recorded MB311.9 MB15,000
neo4j5.26.29F20.3760.6801.076Not recorded MB635.7 MB15,000
i

graph-diagnostics

complete

Pokec-small

All 29 Pokec-small operation and mixed-workload cells across Antfly v0.2.0, Neo4j, and Memgraph.

Methodology scope · protocol · interpretation

Graph Database Benchmark v2 Methodology

Scope and provenance

This benchmark has two lanes and does not calculate a composite winner. LSQB-derived is an Antfly-owned anchored microbenchmark over LSQB data. The Pokec suite is a clean-room implementation informed by the public categories and workload ratios described by Memgraph’s Benchgraph material. It reuses the public Pokec import files, not Benchgraph implementation code. Neither lane is an audited LDBC result.

The scorecard keeps these measurements separate:

LaneScorecard metricsDirection
LSQB-derived F2warm serial p50, warm serial p99latency lower
Pokec W1completed QPS, peak process RSSQPS higher; RSS lower

Full statistics, errors, run ranges, and raw samples remain mandatory even when the scorecard is used.

Engines and equal client work

The comparison is Antfly, Neo4j 5.26.29, and Memgraph 3.12.0. Kuzu is excluded because it is not exercised through a comparable network service. Every timed throughput cell uses the same Go executable, deterministic schedule, quantile implementation, response-consumption rule, worker count, and wall-clock. Antfly is accessed over persistent HTTP/1.1; both peers use the same official Neo4j Go Bolt driver. Transport is part of observed client latency and is reported, not hidden.

Only equivalent User(id) and benchmark-namespace ID indexes are created. There is no engine-specific query tuning. Each run starts from a fresh database and performs complete correctness checks before timing. Mutating cells use a reserved BenchUser namespace so source reads cannot change; that namespace is restored to its 1,024-node ring baseline after every mutating cell. Timed requests are never retried. Errors are retained and exclude a run from the publication gate.

LSQB-derived lane

The pinned source, data loading, parameter selection, BLAKE3 result oracle, and N1/P2/F2 definitions are specified in graph-lsqb-derived.md. The public LSQB-derived metric is warmed serial latency for this exact endpoint-filtered lookup, returning matching Post IDs:

(Forum)-[:CONTAINER_OF]->(Post)-[:HAS_TAG]->(Tag {id: $tag_id})

Unfiltered P2 C12 throughput remains a retained diagnostic. It is not part of the graph scorecard or public filtered-lookup claim. Default, medium, and full use LSQB SF0.003, SF0.1, and SF1 respectively.

Pokec data and parameter oracle

Profiles use the public Memgraph Pokec import files:

ProfileDatasetUsersDirected FRIEND edgesAnchors
quickPokec-small10,000121,71612
mediumPokec-medium100,0001,768,51548
fullPokec-large1,632,80330,622,564128

The harness records the downloaded source SHA-256 and refuses unexpected node or edge counts. Anchors are selected deterministically across out-degree deciles with seed 0xB37C4. Every selected anchor must return its complete result below 900 rows through four hops; this stays below rc18’s 1,000 pattern match ceiling rather than comparing truncated results.

Expansion semantics are one endpoint result per directed walk. Antfly uses a chain of fixed one-hop pattern steps. Cypher uses one fixed MATCH clause per hop, avoiding vendor differences in variable-length path uniqueness. The offline SQLite oracle stores the exact result count and canonical BLAKE3 digest including multiplicity for every parameter. Aggregates and shortest path have exact scalar oracles. All 101 quick-profile checks per engine/run must pass before timing. Writes are executed and verified in the isolated benchmark namespace.

Pokec operations

Cell identifierFull operation name
R1exact indexed user lookup returning the stored user document
WNinsert a new benchmark user node
U1increment one benchmark-user property
WEadd one directed benchmark friendship edge
AG1whole-table age buckets and counts
AG2whole-table age count/min/max/sum/average
E1–E4exact fixed 1-, 2-, 3-, or 4-hop directed expansion
E2Fexact 2-hop expansion with endpoint age >= 18
N2concatenated exact 1-hop and exact 2-hop neighborhood
SPdirected unweighted shortest path, maximum depth 8

Four-hop expansion (E4) returns endpoints reached by exactly four directed hops; one-plus-two-hop neighborhood (N2) concatenates the exact one-hop and exact two-hop neighborhoods (including walk multiplicity). They measure different work and remain separate rows.

Every operation has an unwarmed serial observation and a prewarmed serial distribution. Isolated throughput uses 12 clients. Each non-mutating operation also receives a 70% operation / 30% write cell, split evenly between node and edge insert. The deterministic realistic workloads are:

  • Mixed analytical/read/update/write workload (W1): 20% analytical (AG1/AG2), 40% exact indexed user lookup, 10% property update, and 30% write split evenly between node and edge mutation;
  • Read-heavy mixed workload (W2): 70% exact indexed user lookup and 30% write;
  • Balanced read/write workload (W3): 50% exact indexed user lookup and 50% write;
  • Write-heavy mixed workload (W4): 30% exact indexed user lookup and 70% write.

How to interpret representative cells

Within one cell, higher completed QPS and lower p50/p95/p99 indicate better serving performance. QPS values across different cells do not compare equal amounts of work.

Exact indexed user lookup (R1) fetches one known user and returns the stored document. Its isolated cell measures focused point-read behavior with 12 clients and thousands of served samples per run.

Directed unweighted shortest path (SP) invokes each engine’s shortest-path primitive with a maximum depth of eight. The deterministic quick-profile parameters select targets one or two hops away, so this cell demonstrates short bounded pathfinding rather than long-path or high-diameter behavior.

Mixed analytical/read/update/write workload (W1) supplies the broadest database-behavior signal. Twelve clients concurrently issue 20% whole-table age analytics, 40% exact user lookups, 10% property increments, and 30% node or edge writes. Slow analytics or mutation maintenance can therefore delay otherwise-fast reads; the cell intentionally captures this cross-operation interference. Low completion counts make its tail percentiles directional, so reports retain counts and every raw response alongside QPS and latency.

Current Antfly rejects transforms against reserved _edges paths. Its WE compatibility request replaces the complete deterministic benchmark edge set through a whole-document upsert, while Neo4j and Memgraph create one edge. Diagnostic presentations disclose that difference and make no publication or apples-to-apples write-throughput claim.

The quick profile uses one-second isolated/mixed cells and two-second W1–W4 cells. Medium uses 5/10 seconds; full uses 15/30 seconds. Warmup is untimed. Every successful timed request is retained in JSONL. Reports contain completed QPS, error counts, p50/p95/p99, per-operation statistics, and peak PID RSS.

Persistent database volume

The honed LSQB SF0.1 F2 lane creates a new, run-labeled Docker local volume for every engine and repetition. Only the complete writable database root is measured (/data for Antfly and Neo4j, /var/lib/memgraph for Memgraph); read-only dataset/tool volumes and client scratch are excluded. A digest-pinned Alpine probe captures whole-volume allocated and apparent bytes once at empty, service-ready-before-ingestion, and post-workload, then at the verified post-stop final barrier. Final allocated bytes are the headline.

All three storage values, their arithmetic mean and range, apparent-byte diagnostics, barrier samples, volume manifests, and lifecycle receipts are retained. A provisional stop timeout remains visible but cannot support a comparative ratio.

Runs, ordering, and reporting

Each profile requires three clean process runs. Engine order rotates by run and uses a different rotation between lanes. Public serial point estimates are the medians of the three run-level p50, p95, and p99 values. Every result row also retains the three run-level percentile records, their min–max ranges, pooled sample percentiles as diagnostics, and all raw samples. Load/index readiness is diagnostic and is never included in query metrics.

summary.json is the machine-readable source of truth. The Markdown report contains the full cell table; scorecard.svg is only the compact two-panel view. There is deliberately no geometric mean or composite rank.

The honed LSQB SF0.1 F2 lane caches only the complete three-engine cohort. Promotion requires Antfly, Neo4j, and Memgraph to each retain three fresh database constructions and process runs, 15,000 timed samples, all three run-level percentile records and ranges, three complete storage receipts and their allocated-byte mean/range, 1,000/1,000 correctness, a valid canonical receipt, and the quiet-host record. The cache identity binds the Antfly subject, both peer image digests, the Linux client and storage-probe image, dataset manifest, harness sources, and protocol. A hit materializes the entire cohort; per-engine cache mixing is not permitted.

Internal fresh-service F2 readiness and convergence

The honed and Circus profiles retain a fresh-service diagnostic that measures how quickly a preloaded graph service becomes useful and settles into its warm filtered-two-hop behavior. It is graph-specific: readiness is followed immediately by the same exact LSQB SF0.1 F2 request used by the warm latency lane. It is not a general process-startup or system-wide Antfly claim.

This cohort is deliberately internal. It is attached to the canonical graph run report and structured result, but the public benchmark-page renderer does not render its table. It is never eligible for the honed publication cache: each honed or gauntlet graph invocation collects it afresh with make graph-f2-warmup-run. The retained diagnostic contract requires:

  • the same Antfly binary, pinned Neo4j and Memgraph images, official LSQB SF0.1 dataset, and Linux/arm64 Docker environment as the primary graph lane;
  • a recorded physical-host state, including whether the honed quiet-host assertion was active, without treating a diagnostic run as publication data;
  • one database construction followed by five fresh service lifecycles per engine, with balanced engine ordering;
  • restart-to-ready measured from immediately before service launch through the first successful engine-native probe: Antfly GET /readyz, Neo4j cypher-shell RETURN 1 plus the pinned-version check, and Memgraph autocommit SHOW VERSION over Bolt;
  • the first F2 latency and first-100 p50/p95 from a fixed 100-anchor panel selected by SHA-256 rank independently of result cardinality;
  • convergence at the first point where three consecutive adjacent 100-query window p50 changes are each within 5%, with a 10,000-query ceiling;
  • steady-state p50/p95 from five deterministic sweeps over all 1,000 anchors after convergence;
  • every timed result checked against the independent count+BLAKE3 oracle, with all 1,000 anchors covered in every engine/lifecycle; and
  • median-of-five run metrics with complete run ranges, raw timestamped samples, lifecycle logs, host evidence, exact schedules, and a canonical receipt.

These seven values are an indivisible internal reporting family: restart-to-ready, first-query, first-100 p50, first-100 p95, queries-to-stable-p50, steady p50, and steady p95. The retained report must show all seven for all three engines; it must not headline convergence while omitting the steady-state latency guardrail or Memgraph.

Bounded internal Maxi diagnostic source

graph-diagnostics canonicalizes medium Pokec and LSQB-derived SF0.1 instrumentation without changing the honed F2 publication protocol. One balanced three-engine collection produces two independent sub-lanes:

  • lsqb-derived-anchored-n1-p2-f2-v1 retains separate warm-serial N1, P2, and F2 median-of-three run percentiles, ranges, result-count buckets, served sample counts, and every count+BLAKE3 parameter oracle; and
  • pokec-graph-operations-v1 retains R1, E1–E4, E2F, N2, SP, AG1, AG2, WN, U1, WE, W1–W4, exact mutation-state checks, and raw schedules on the Pokec-medium corpus.

The default runner passes zero throughput seconds, so it never starts the P2 concurrency workload. It also never starts the five-lifecycle fresh-service cohort. graph-p2-c12-sf01-run and graph-f2-warmup-run retain those protocols as explicit opt-in diagnostics. SF1 and SF10 likewise require explicit scale targets and never enter the default gauntlet.

The finalizer rejects timed errors, missing runs, failed count/hash/state oracles, and any result-budget contact. The canonical result uses graph-diagnostics-v2 with classification internal_diagnostic. PID RSS remains under diagnostic_process_rss; the source declares comparable_resource_metrics: false, emits no memory or storage chart, and defines no composite winner. This source enters the gauntlet and Maxi incubation views only, never the honed allowlist or public graph section.

Qualification and publication

The default command is a small, complete optimization loop with a target wall time below 15 minutes. Medium and full are explicit diagnostic commands. A mixed native-macOS/container run is qualification-only because its process RSS views are not comparable across engines.

The release-facing honed F2 lane is a separate, environment-qualified publication protocol. Antfly, Neo4j, and Memgraph all run sequentially inside the same Docker Desktop Linux/arm64 VM on an explicitly quiescent Apple Silicon host. The published claim must name that environment and is limited to warm serial filtered two-hop latency; it is not a bare-metal Linux result or a claim about general graph-database performance. Publication requires:

  • the exact v0.2.0 Linux/arm64 binary and expected SHA-256;
  • the pinned Neo4j 5.26.29, Memgraph 3.12.0, and Linux client image digests;
  • official LSQB SF0.1 with 432,235 nodes and 1,827,523 relationships;
  • three fresh database constructions and process runs per engine, each on a newly created labeled database volume;
  • five warmed serial sweeps per run over 1,000 deterministic anchors;
  • 1,000/1,000 count+BLAKE3 correctness in every engine/run and zero timed errors;
  • median run-level p50/p95/p99 with all run ranges, pooled diagnostics, raw samples, lifecycle logs, and the physical-host record retained; and
  • a canonical receipt for the indivisible three-engine cohort.

The broader graph-v2/Pokec publication gate remains native-Linux-only and is not satisfied by this bounded F2 artifact.

Run evidence parameters · variation · provenance

Benchmark parameters

{"classification":"internal_diagnostic","comparable_resource_metrics":false,"default_runtime_scope":{"fresh_service":false,"lsqb_scale_factor":null,"p2_concurrency":false,"pokec_profile":"quick"},"sub_lanes":["pokec"]}

Peer versions

Peer versions were not recorded in the published result fields.

Evidence digests

Receipt
fe72bd7fa2f9b7e14c8f05e08aa909126ec6340f31abb4fb3c1a2077c789159f
Aggregate
5a4b25683c9fa1e997ba0b194a26423cbd6e095a8a7fd67f034a2f5968cb3884
Provenance
fe08dc2dca7ea1463edfd9aba8d386e0ded389f9230dd1cee8f0c3664846cd11
Harness commit
2d73a9f1f1fcf962f4c70f6d51fdc55a8d4239e3

Scope notes

  • Local Linux/x86_64 diagnostic on one unqualified laptop host; compare QPS and latency only within the same task. PID RSS does not support cross-engine resource comparison.
  • Antfly edge mutation (WE) replaces the deterministic benchmark edge set through a whole-document upsert because graph-edge transforms reject reserved _edges paths.
Selected measurement
Completed
Antfly
v0.2.0 ·
Runtime
Elapsed time not captured
Platform
linux · x86_64
Machine
Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz · 8 CPU · 16.6 GB
Build
ReleaseFast · Zig official-release-archive

Completion time is taken from the run’s recorded validation time; this older result predates direct finish-time capture.

Local Linux/x86_64 diagnostic on one unqualified laptop host; compare QPS and latency only within the same task. PID RSS does not support cross-engine resource comparison.

Antfly edge mutation (WE) replaces the deterministic benchmark edge set through a whole-document upsert because graph-edge transforms reject reserved _edges paths.

Pokec-small throughput by task and engine

Antfly v0.2.0 (56a1b1a5) · linux-x86_64 · Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz · Pokec-small · ReleaseFast · three runs · 1-client serial sweeps · 12-client 1s task cells / 2s mixes · seed 0xB37C4 · Each task resets red→yellow→green from lowest to highest QPS; compare within the same task/row only

Pokec-small graph operations

Antfly v0.2.0 · 56a1b1a5

TaskAntflyNeo4jMemgraph
Serial read sweep (unwarmed)QPS 9.5 · p50 13.6 / p95 371.9 / p99 386.2 msQPS 13.5 · p50 74.5 / p95 164.1 / p99 171.9 msQPS 277.4 · p50 0.5 / p95 15.5 / p99 23.4 ms
Serial read sweep (prewarmed)QPS 12.4 · p50 2.6 / p95 379.5 / p99 407.2 msQPS 181.1 · p50 3.8 / p95 13.2 / p99 17.2 msQPS 206.3 · p50 0.7 / p95 24.6 / p99 29.2 ms
Isolated · exact lookup (R1)QPS 4,005.5 · p50 2.4 / p95 7.6 / p99 10.6 msQPS 1,334.7 · p50 7.8 / p95 18.9 / p99 29.2 msQPS 9,475.5 · p50 0.8 / p95 3.3 / p99 6.7 ms
Isolated · age buckets (AG1)QPS 2.4 · p50 4,984.6 / p95 5,083.7 / p99 5,084.9 msQPS 401.9 · p50 28.7 / p95 46.0 / p99 61.6 msQPS 719.5 · p50 15.6 / p95 27.8 / p99 36.8 ms
Isolated · age stats (AG2)QPS 2.3 · p50 5,051.3 / p95 5,197.2 / p99 5,245.0 msQPS 365.6 · p50 30.8 / p95 55.0 / p99 66.7 msQPS 288.7 · p50 39.7 / p95 66.4 / p99 89.9 ms
Isolated · 1-hop expansion (E1)QPS 2,004.6 · p50 4.7 / p95 15.4 / p99 21.5 msQPS 1,888.2 · p50 5.1 / p95 13.9 / p99 23.6 msQPS 7,944.2 · p50 1.0 / p95 4.2 / p99 7.8 ms
Isolated · 2-hop expansion (E2)QPS 559.2 · p50 16.8 / p95 50.3 / p99 77.0 msQPS 1,761.8 · p50 5.7 / p95 15.0 / p99 25.0 msQPS 6,219.6 · p50 1.2 / p95 5.5 / p99 10.0 ms
Isolated · 2-hop age filter (E2F)QPS 893.4 · p50 12.5 / p95 22.9 / p99 28.5 msQPS 1,984.4 · p50 5.0 / p95 13.7 / p99 24.3 msQPS 7,865.5 · p50 1.1 / p95 4.0 / p99 7.4 ms
Isolated · 3-hop expansion (E3)QPS 213.6 · p50 49.2 / p95 113.0 / p99 154.5 msQPS 828.1 · p50 11.3 / p95 37.1 / p99 59.4 msQPS 3,396.7 · p50 3.0 / p95 8.1 / p99 12.8 ms
Isolated · 4-hop expansion (E4)QPS 21.5 · p50 516.7 / p95 713.4 / p99 756.1 msQPS 168.9 · p50 63.1 / p95 132.3 / p99 166.2 msQPS 666.9 · p50 16.6 / p95 32.8 / p99 41.9 ms
Isolated · 1+2-hop neighborhood (N2)QPS 475.7 · p50 22.2 / p95 51.7 / p99 76.3 msQPS 1,520.3 · p50 5.6 / p95 22.5 / p99 39.4 msQPS 6,268.1 · p50 1.3 / p95 5.1 / p99 9.3 ms
Isolated · shortest path ≤8 (SP)QPS 7,364.8 · p50 1.4 / p95 3.5 / p99 4.8 msQPS 2,294.1 · p50 4.3 / p95 11.8 / p99 21.6 msQPS 142.4 · p50 82.3 / p95 118.4 / p99 133.2 ms
Isolated · node insert (WN)QPS 14.0 · p50 682.8 / p95 1,346.5 / p99 1,506.9 msQPS 475.2 · p50 23.1 / p95 44.0 / p99 51.8 msQPS 6,411.5 · p50 1.3 / p95 4.7 / p99 8.9 ms
Isolated · property update (U1)QPS 17.9 · p50 531.2 / p95 1,250.1 / p99 1,377.1 msQPS 846.3 · p50 13.5 / p95 23.3 / p99 27.9 msQPS 7,255.4 · p50 1.1 / p95 4.3 / p99 7.5 ms
Isolated · edge mutation (WE)QPS 8.3 · p50 1,168.0 / p95 1,707.9 / p99 1,845.9 msQPS 649.7 · p50 16.9 / p95 33.7 / p99 42.3 msQPS 5,786.5 · p50 1.5 / p95 5.5 / p99 9.7 ms
30% writes · exact lookup (R1)QPS 33.3 · p50 204.2 / p95 965.5 / p99 1,139.4 msQPS 1,308.4 · p50 4.2 / p95 31.1 / p99 52.9 msQPS 8,405.5 · p50 0.9 / p95 3.6 / p99 7.3 ms
30% writes · age buckets (AG1)QPS 2.5 · p50 4,785.5 / p95 4,827.0 / p99 4,848.3 msQPS 478.5 · p50 22.5 / p95 45.9 / p99 54.0 msQPS 892.8 · p50 12.6 / p95 25.9 / p99 34.6 ms
30% writes · age stats (AG2)QPS 5.8 · p50 1,552.7 / p95 2,066.7 / p99 2,079.7 msQPS 532.8 · p50 20.0 / p95 45.5 / p99 57.6 msQPS 371.4 · p50 31.2 / p95 62.4 / p99 73.9 ms
30% writes · 1-hop expansion (E1)QPS 29.7 · p50 198.9 / p95 1,126.8 / p99 1,128.8 msQPS 1,911.3 · p50 2.6 / p95 21.1 / p99 43.7 msQPS 6,675.7 · p50 1.2 / p95 4.8 / p99 9.2 ms
30% writes · 2-hop expansion (E2)QPS 31.2 · p50 35.1 / p95 1,134.6 / p99 1,155.4 msQPS 2,114.6 · p50 2.6 / p95 18.7 / p99 34.5 msQPS 6,354.3 · p50 1.3 / p95 5.3 / p99 9.3 ms
30% writes · 2-hop age filter (E2F)QPS 35.3 · p50 197.2 / p95 803.9 / p99 804.3 msQPS 2,356.7 · p50 2.3 / p95 15.9 / p99 26.4 msQPS 7,727.5 · p50 1.1 / p95 3.9 / p99 7.1 ms
30% writes · 3-hop expansion (E3)QPS 45.7 · p50 228.5 / p95 607.4 / p99 618.9 msQPS 1,921.8 · p50 4.4 / p95 16.1 / p99 22.5 msQPS 2,840.5 · p50 2.5 / p95 13.4 / p99 21.9 ms
30% writes · 4-hop expansion (E4)QPS 15.9 · p50 500.6 / p95 1,134.3 / p99 1,312.8 msQPS 448.4 · p50 24.4 / p95 56.6 / p99 72.8 msQPS 612.5 · p50 16.6 / p95 49.1 / p99 75.1 ms
30% writes · 1+2-hop neighborhood (N2)QPS 30.6 · p50 279.1 / p95 982.5 / p99 990.2 msQPS 2,215.6 · p50 2.8 / p95 16.0 / p99 26.1 msQPS 6,572.0 · p50 1.3 / p95 4.8 / p99 8.7 ms
30% writes · shortest path ≤8 (SP)QPS 39.0 · p50 295.0 / p95 944.9 / p99 946.5 msQPS 2,242.3 · p50 2.6 / p95 16.5 / p99 25.1 msQPS 189.8 · p50 62.4 / p95 112.4 / p99 133.5 ms

Pokec-small read/write mixes

Antfly v0.2.0 · 56a1b1a5

TaskAntflyNeo4jMemgraph
Mixed workload · 20/40/10/30 (W1)QPS 9.2 · p50 727.0 / p95 2,384.1 / p99 2,384.9 msQPS 1,514.8 · p50 8.4 / p95 17.7 / p99 23.3 msQPS 1,547.5 · p50 3.8 / p95 29.8 / p99 42.1 ms
Read-heavy mix · 70/30 (W2)QPS 31.5 · p50 338.5 / p95 913.8 / p99 953.2 msQPS 3,216.5 · p50 1.5 / p95 11.2 / p99 16.1 msQPS 7,366.1 · p50 1.1 / p95 4.1 / p99 7.9 ms
Balanced mix · 50/50 (W3)QPS 26.2 · p50 335.1 / p95 1,074.7 / p99 1,355.8 msQPS 2,392.0 · p50 4.9 / p95 11.7 / p99 16.8 msQPS 8,388.6 · p50 1.0 / p95 3.3 / p99 6.1 ms
Write-heavy mix · 30/70 (W4)QPS 16.1 · p50 481.9 / p95 1,980.5 / p99 2,182.8 msQPS 1,800.8 · p50 7.7 / p95 12.9 / p99 19.2 msQPS 8,000.3 · p50 1.1 / p95 3.6 / p99 6.4 ms
ii

graph-lsqb-official

missing

Official LSQB

The exact upstream q1–q9 files provide a capability and correctness matrix during incubation.

Methodology scope · protocol · interpretation

Official LSQB capability and correctness lane

This lane wraps the unmodified LSQB source at commit 62136445b6bc0be8a0ad60ea008b5faa16e34546. It runs the upstream example dataset and hashes the exact cypher/q1.cypher through cypher/q9.cypher files.

Neo4j 5.26.29 and Memgraph 3.12.0 execute each upstream scalar count(*) query. Antfly receives only representable requests. Q1 permits one correctness-only materialization with a preregistered max_results value of 900 when the upstream count falls below that cap. Q2–Q9 receive explicit unsupported classifications; the adapter performs no client-side joins, filtering, or aggregation.

The canonical artifact uses schema graph-lsqb-official-v1, classification capability_matrix, and a complete 27-cell engine/query matrix. It reports no latency, throughput, resource point, or audited LSQB score. Missing cells, upstream validation failures, unexpected unsupported-query requests, or query-file drift fail the artifact. Unsupported cells alone preserve a complete capability result.

Peer execution retains the established cohort: neo4j@sha256:d9dd3dc7d1c78fa959191ff02dbdcbefadceaf83eee23428fb92a58cac8ad3fe and memgraph/memgraph@sha256:c162cb9a6f76dac6080119da919d9b36e69c8b982af7bf34dd7df2b3723bd69c. Linux/arm64 execution uses the pinned CIRCUS_LINUX_IMAGE runtime. Every live run records the asserted Antfly tag, commit, executable SHA-256, query hashes, dataset manifest, validator output, raw responses, and engine logs.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed official-LSQB capability artifact has received an explicit selection.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
iii

graph-snb-interactive

missing

SNB Interactive

A bounded SF0.1 qualification covers four exact SNB Interactive read operations against Antfly.

Methodology scope · protocol · interpretation

LDBC SNB Interactive v1 bounded read qualification

This incubation lane pins the official Interactive v1.2.0 driver at 4cd13735f964406ad34f34ccd5bef4d6e6c284d0 and Hadoop datagen v1.0.0 at 37d35f40f5023fcf1afd3b6d0984f71c202f4bca. Upstream submodules remain unmodified.

The default gauntlet uses official SF0.1 CsvCompositeMergeForeign-LongDateFormatter data and one fresh Antfly lifecycle. SF1 and SF10 require explicit scale targets. Downloaded or generated data stays under .data/; provenance retains the source URL, archive SHA-256, extracted file manifest, staged node/edge counts, and parameter digest.

The exact qualified subset contains four read operations:

  • LdbcShortQuery1PersonProfile: versioned Person lookup returning first name, last name, birthday, location IP, browser, city, gender, and creation date;
  • LdbcShortQuery4MessageContent: versioned Post/Comment lookup returning content-or-image and creation date;
  • LdbcShortQuery5MessageCreator: one-hop HAS_CREATOR pattern returning the exact creator identifier and names; and
  • LdbcQuery13: unweighted shortest path over KNOWS, returning the path length.

The harness selects deterministic parameters by SHA-256 rank and constructs independent SQLite oracles from the retained CSV files. Every parameter passes exact correctness before timing. Timed records include served-only p50/p95/p99, sample counts, and zero request errors. Result-budget contact, missing parameters, response errors, or oracle mismatches fail the artifact.

All 29 Interactive v1 operations remain visible. Unsupported operations receive explicit semantic reason codes, no request, no fallback, no client-side join/filter/order/aggregation, and no timing. Updates remain unsupported because each official update changes related graph entities or edges atomically.

The canonical artifact uses graph-snb-interactive-v1-qualification-v1, classification partial_read_qualification, and official_score_eligible: false. It does not run the official mixed workload, use official frequencies, report throughput, claim complete conformance, or qualify for public publication. Pinned Neo4j and Memgraph comparison support may follow in a later protocol; this bounded default currently qualifies Antfly against exact official operation semantics.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed SNB Interactive v1 qualification artifact has received an explicit selection.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
VII

8 lanes without selected evidence

Missing evidence

i

vector-filtered-ann

missing

Filtered ANN

Filtered vector search quality and performance across the portable and honed workload profiles.

Methodology scope · protocol · interpretation

Filtered ANN Methodology

This benchmark is intentionally separate from the unfiltered VectorDBBench matrix. The honed publication workload measures equality-filtered, tenant-scoped vector search; the broader portable matrix and gauntlet retain numeric-filter diagnostics. All use exact filter-aware ground truth and the same database adapters and service topology as the regular vector benchmark.

Portable 50K matrix

The Circus-owned portable matrix loads each engine once with the vector, integer ID, and a deterministic categorical bucket, then runs six scenarios:

  • numeric tails retaining 10%, 2%, 1%, and 0.2% of the corpus;
  • a fixed categorical bucket retaining 1% / 500 scattered rows; and
  • a rotating categorical bucket, changed per query, also retaining 1%.

Rows use bucket_{id % 100}. The fixed case selects bucket_037; the rotating case selects (query_index * 37 + 11) % 100, which visits every bucket ten times over the 1,000-query test set. Each scenario has exact cosine top-100 ground truth. The 0.2% numeric point deliberately leaves exactly 100 eligible rows and is the minimum valid selectivity for top-100.

Each database performs three complete search sweeps, with scenario order deterministically shuffled per database and repetition. Reports use the median with min-max whiskers and show Recall@100, peak QPS, and p99 at the concurrency producing peak QPS. Performance execution fails closed while unrelated benchmark processes or containers own the shared host.

Honed profile

  • Dataset: Small OpenAI, 50,000 vectors, 1,536 dimensions, cosine distance
  • Tenant model: 100 equal buckets defined by bucket_{id % 100}, with 500 vectors per tenant
  • Filter: categorical equality on the tenant bucket selected for each query
  • Quality schedule: (source_query_index * 37 + 11) % 100, which visits every tenant and remains stable across the deterministic calibration/publication partition
  • Throughput schedule: every worker rotates across tenant buckets so the measurement is not a repeated hot-filter cache lookup
  • Top-k: 100
  • Engines: Antfly, Weaviate, Elasticsearch, Milvus, pgvector, and Chroma. This keeps the honed comparison focused on the source benchmark target, a mainstream hybrid-search engine, a vector-native engine, and the ubiquitous Postgres extension baseline, while retaining the popular embedded/developer-oriented vector store.
  • Lifecycle: three fresh indexes per engine. Each index is tuned only on the deterministic 200-query calibration partition, then measured on the disjoint 800-query holdout. The same three lifecycles define performance, memory, and storage aggregates.
  • Storage: each lifecycle uses one newly labeled Docker local volume at the engine’s complete persistence root. Capture whole-volume allocated/apparent bytes once at empty, ready, and post_workload, then at the verified post-stop final barrier before reclamation. Host paths are ineligible. Retain every value and report the arithmetic mean and range across all three lifecycles.
  • Search mode: serial latency/recall plus QPS at concurrency 1, 8, and 32 for 10 seconds each.

Antfly calibration-only topology qualification

Before the three publication lifecycles, Antfly alone qualifies shard counts 1, 2, and 4 on fresh indexes using only the same deterministic 200-query calibration partition. Each topology sweeps the preregistered search-effort ladder 0, 0.025, 0.05, …, 0.35; the lowest effort reaching recall 0.955 is selected. Holdout queries, publication concurrency, and publication metrics are forbidden inputs to this topology decision.

When all three topology candidates qualify, the selector minimizes calibration (p95, p99, shard count) in that order. If any candidate is quality-negative or operationally incomplete after one retry, publication uses the preregistered one-shard control rather than selecting from a partial successful set. The chosen shard count is frozen across all three Antfly publication lifecycles and included in their cache identity.

Gauntlet profile

  • Dataset: Medium OpenAI, 500,000 vectors, 1,536 dimensions, cosine distance
  • Filter: id >= 495,000, leaving 1% / 5,000 candidates
  • Engines: the same six-engine set. Qdrant is not part of either profile. Quickwit is a lexical/log-search engine in this suite and does not expose a comparable VectorDBBench filtered-ANN adapter.
  • Metrics: same as the honed profile, with the exhaustive concurrency 1, 5, 10, 20, 30, 40, 60, and 80 sweep at 30 seconds per point
  • Peak-memory sampling is enabled by the enclosing gauntlet benchmark profile

Correctness and fairness

The honed adapters implement categorical equality against the same labels field and load the same 100-bucket assignment. Its exact cosine top-100 ground truth uses the tenant selected for each source query. The query schedule is applied before the deterministic 200/800 partition so each retained vector is paired with the same tenant in calibration, publication, and independent reproduction.

The gauntlet’s numeric adapters implement inclusive >= semantics. VectorDBBench compares each result to neighbors computed within the surviving candidate set, so unfiltered or post-filtered top-k results lose recall rather than appearing artificially fast. Results report recall, nDCG, peak concurrent QPS, the concurrency and p99 latency at that peak, p95/p99 serial latency, insert time, and total load time. Index and query knobs are recorded in the command logs.

Filtered services use their own container names, data roots, result labels, logs, status rows, and host ports. Antfly defaults to port 28081 so it cannot attach to or stop the regular/full-text Antfly service on port 28080.

Canonical output retains every storage.json, barrier sample, declared volume, trial value, arithmetic mean, and range under raw/storage. Final allocated bytes are the headline; apparent bytes and engine-reported index sizes are diagnostics. Filtered peer storage appears in the comparative review only when the existing review-inclusion gate passes, while canonical/raw evidence is always retained.

The portable matrix still does not constitute a complete claim about filtered search. Planned follow-ups add vector-correlated categories, skewed hot/cold filter churn, conjunctions/exclusions, concurrent-ingest interference, matched-recall tuning, and 500K/1M datasets.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
ii

fulltext-search-benchmark-game

missing

Search Benchmark Game

Full-text query throughput and latency grouped by query class and result window.

Methodology scope · protocol · interpretation

Search Benchmark Game Methodology

What this lane measures

This is an end-to-end, self-hosted database comparison over the first 250,000 documents in the Search Benchmark Game Wikipedia corpus. Every timed adapter uses a persistent database connection and requests ranked document IDs without stored document bodies. Tantivy is deliberately absent: it is an embedded search library, while every measured row here is a database service.

The run uses the 902 upstream term, union, intersection, and phrase queries. The 60 mixed required/optional and negated Lucene-syntax queries remain excluded because Antfly cannot represent their matching and scoring semantics directly. If the remaining workload proves too Lucene-oriented for database comparison, that will motivate a separate benchmark rather than further changing this one.

Database matrix and capability policy

  • Antfly 0.2.0-rc.18: term, union, intersection, phrase
  • Elasticsearch 8.15.3: term, union, intersection, phrase
  • Weaviate 1.38.2: term, union, intersection; exact phrase unsupported
  • Quickwit 0.8.2: term, union, intersection, phrase
  • PostgreSQL 16 from the pgvector image: term, union, intersection, phrase; pgvector is not involved in lexical execution
  • Milvus 2.5.8: retained as unsupported because its BM25 raw-text input is a VARCHAR capped at 65,535 bytes, while 20 corpus documents exceed that limit and the maximum is 202,798 bytes
  • Chroma self-hosted: retained as unsupported because its text surface provides containment/regex filtering rather than ranked lexical top-k retrieval; the richer Chroma Search API is cloud-only

Missing capabilities are never emulated client-side. Public output uses —* for a product limitation and failed† for a setup or execution failure, with the reason preserved in JSON and rendered beside the table.

Execution protocol

The benchmark runs TOP_10 and TOP_100 at concurrency 1 and 8. Each cell has a five-second warmup followed by two measured rounds. Concurrency uses one persistent connection per worker; individual request latency and aggregate QPS are both recorded. Only one database is timed at once. Indexing is sequential, uses the unchanged corpus, and uses native bulk paths (COPY for PostgreSQL, bulk APIs elsewhere).

Antfly uses a prebuilt release binary; the benchmark never builds Zig. It runs one shard and sends fields: []. Elasticsearch uses one primary shard, zero replicas, a 1 GiB heap, and a one-segment force merge. Weaviate runs one node with vectorization disabled. Quickwit runs one node with a positional, fieldnorm-enabled text index and BM25 score ordering; only external IDs are stored. PostgreSQL uses a stored tsvector, GIN index, and ts_rank_cd ordering.

Where configurable, adapters approximate Antfly’s fixed Bleve analyzer with standard/word tokenization, lowercase normalization, and English stopwords. Quickwit’s built-in default tokenizer lowercases but does not expose a matching stop-word filter. Residual analyzer and scoring differences are reported through an untimed top-10 ID/count diagnostic; exact cross-engine ranking is not a pass condition.

Interpretation

The headline table shows TOP_10 concurrency-8 p95 latency by query class so partial capability is visible. Full artifacts retain p50/p95/p99, QPS, sample counts, status, and reasons for TOP_10/TOP_100 at both concurrency levels. This benchmark has no relevance judgments, so it supports performance and capability claims only—not claims that one engine ranks documents more correctly.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
iii

document-omnidocbench

missing

OmniDocBench

Document parsing and structure-recovery quality across the OmniDocBench evaluation surface.

Methodology scope · protocol · interpretation

OmniDocBench Methodology

benchmarks/OmniDocBench is the raw benchmark checkout and stays pointed at the Antfly-owned OmniDocBench origin. This harness directory contains antfly-circus-specific adapter code, methodology notes, generated prediction directories, and OmniDocBench evaluator outputs.

Measurement surface

OmniDocBench measures document parsing quality, not plain OCR alone. Each engine must produce one markdown prediction per page; OmniDocBench then scores text recognition, table reconstruction, formula rendering, and reading order.

Antfly is invoked through the central Bastille handoff: antfly-circus passes the exact benchmark binary as ANTFLY_BIN, and the adapter only consumes that binary. It does not discover or substitute another Antfly executable.

Default smoke profile

  • Dataset: OmniDocBench demo data
  • Prediction format: one markdown file per page
  • Evaluation: OmniDocBench end2end config shape
  • Smoke behavior: verify adapter wiring and output paths without claiming full OmniDocBench leaderboard coverage

Full benchmark profile

The default full profile runs --engine antfly --protocol page-image over the bundled OmniDocBench demo subset: 18 page images. It writes one Antfly-generated markdown prediction per page, evaluates with OmniDocBench, and reports quality metrics first: Overall, text edit distance, table TEDS, formula CDM, and reading-order edit distance. Prediction throughput is reported separately as pages/s.

Set ANTFLY_DOC_MODEL_DIR to the explicit reader model directory and ANTFLY_BIN to the exact Antfly binary under test. The adapter intentionally does not substitute bundled demo predictions for missing Antfly output.

Protocols and peers

  • page-image: runnable with the bundled demo data. Engines receive raster page images and must emit markdown files whose names match the OmniDocBench image stems.
  • native-pdf: dataset/API-gated. It is blocked unless PDF inputs and a compatible native-PDF engine path are configured. The adapter does not silently rasterize PDFs and call that native PDF parsing.

Open-source peer rows are wrapper-based. Configure command templates with OMNIDOCBENCH_MINERU_CMD, OMNIDOCBENCH_MARKER_CMD, OMNIDOCBENCH_DOCLING_CMD, or OMNIDOCBENCH_OCR_BASELINE_CMD. Templates may use {input}, {output}, {output_dir}, and {stem} placeholders. The OCR-only baseline can also use TESSERACT_BIN or tesseract on PATH.

Record the exact image/PDF input set, command template or Antfly command, model directory/backend selected, protocol, worker counts, whether CDM is enabled, and all generated OmniDocBench result JSON files under benchmarks/OmniDocBench-harness/result. The full 1651-page OmniDocBench dataset is not bundled in this checkout; pull it from the upstream Hugging Face/OpenDataLab dataset before reporting full benchmark coverage.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
iv

document-ohr-bench

missing

OHR-Bench

Raw-PDF ingestion, extraction, OCR fallback, page-aware indexing, and evidence retrieval over the OHR-Bench corpus.

Methodology scope · protocol · interpretation

OHR-Bench Antfly adapter

This adapter runs a curated internal qualification, a deterministic 10% sample, and the complete OHR-Bench corpus against Antfly. It does not modify the upstream clone.

The curated qualification contains 11 documents across all seven domains. It includes every PDF regression found during the first full-corpus attempt, an OCR-required scan, the largest corpus PDF, an encrypted PDF, a filename that exercises URL encoding, and QA-backed representatives. Antfly owns PDF retrieval, extraction, OCR fallback, chunking, embedding, and indexing. The adapter then evaluates lexical and hybrid retrieval with OHR-Bench’s official correct-document/correct-page gate and word-level evidence LCS.

The PDF dataset has conflicting surface metadata: its Hugging Face card says CC-BY-4.0, while the upstream README restricts it to research and non-commercial use. This harness follows the stricter statement. Do not publish or use these artifacts as product/marketing results without a separate review.

Commands

Run these from the antfly-circus repository root. Plain make shows them.

make ohr-bench-setup
make ohr-bench-smoke
make ohr-bench-download
make ohr-bench-qualify
make ohr-bench-report
make ohr-bench-medium
make ohr-bench-medium-report
make ohr-bench-full
make ohr-bench-full-report

ohr-bench-download downloads the public pdfs.zip (about 1.52 GB), verifies its SHA-256 digest, and extracts it below ignored .data/ohr-bench/. Setup also clones the OHR-Bench annotations at the pinned upstream commit into ignored .repos/OHR-Bench/; the upstream repository is not vendored or modified.

ohr-bench-qualify uses ~/.local/bin/antfly-pdf-ocr by default, starts it on port 28580 with an isolated data directory, and writes artifacts to results/ohr-bench/qualification/. Each source row contains a URL such as http://127.0.0.1:18085/law/example.pdf; Antfly’s artifact backfill fetches that URL and performs all parsing itself. The harness starts a loopback-only static PDF byte origin with no directory listing or non-PDF access. It is not a parser and does no OCR, embedding, or transformation. DocsAF and inference sidecars are not used. Override the binary with OHR_ANTFLY_BIN=/absolute/path/to/antfly.

ohr-bench-medium deterministically samples 10% of each domain (129 PDFs) while forcing all curated fixtures into the sample. ohr-bench-full ingests all 1,261 PDFs into seven domain-scoped tables and evaluates all 8,498 questions in lexical and hybrid lanes. Run the qualification before either larger cold ingest.

Antfly’s embedded inference registry loads antflydb/Florence-2-base for OCR and BAAI/bge-small-en-v1.5 for 384-dimensional embeddings from ~/.antfly/inference/models. Override that directory with OHR_MODELS_DIR=/absolute/path. The harness deliberately has no configuration for external inference URLs.

Every load uses the public linear-merge API with sync_level: full_index. Before evaluation, the harness fetches document_units_v1 for every source and requires its unit count to equal an independent pypdf page count and its chunk count to be nonzero. It also reconciles every source URL with the byte origin’s access log, rejects inline/non-HTTP sources and artifact errors, and requires linear-merge cleanup to converge. The OCR-required fixture must show a successful OCR selection. Per-document evidence is retained in coverage.jsonl, including ingest wall time and OCR attempted/selected/retained/ failed counts; the aggregate structural gate is coverage-summary.json.

Artifact-level extraction failures do not stop evaluation. The adapter scores all questions, records zeros for unavailable evidence, produces summary.json and summary.md, and fails only at the final verification step. Infrastructure failures that prevent the run from continuing still stop immediately and write failure.json. A report whose structural gate failed labels its retrieval metrics diagnostic rather than benchmark-comparable.

The curated qualification has an additional content-quality gate. Returned hits may not equal a known normalized OCR prompt echo, and every selected QA-backed document must have at least one hybrid top-5 evidence-page result with positive word-LCS. Medium and full runs reject prompt echoes but do not turn benchmark score magnitude into a pass/fail threshold. Reports also retain unique trivial-text hits, per-document positive-LCS counts, artifact failures, and the slowest ingest documents.

A stopped run preserves failure.json, checkpoints, coverage collected so far, the run fingerprint, and antfly.log. Resume only with the same corpus manifest, binary digest/source SHA, models, and extraction configuration:

make ohr-bench-medium OHR_RESUME=1

The harness never builds Antfly.

Metrics

  • Primary: top-1 correct evidence page and mean word-level evidence LCS.
  • Diagnostic: top-5 correct evidence page and query latency.
  • Setup: cold PDF extraction/OCR/chunk/embed/index wall time.

OHR evidence pages are zero-based. Antfly PDF provenance is one-based, and the adapter tests and applies that conversion explicitly. Queries are isolated by OHR domain, matching the upstream retriever’s per-domain search behavior.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
v

rag-mtcb

missing

MTCB

Chunking and retrieval behavior measured through the MTCB Antfly benchmark.

Methodology scope · protocol · interpretation

MTCB Antfly Benchmark

MTCB evaluates retrieval quality for chunked RAG corpora. The upstream harness chunks documents, embeds chunks and questions, retrieves top-k chunks, and scores whether the gold passage appears in the retrieved chunk set.

Antfly Surface

This adapter keeps MTCB’s evaluator and metric calculations, but replaces the in-memory vector store with Antfly external-vector retrieval:

  • one Antfly table per MTCB dataset evaluator;
  • one external aknn_v0 cosine vector index named vec;
  • chunk text is stored as table metadata and the vector is inserted in _embeddings.vec;
  • queries use /api/v1/query with embeddings.vec and the requested limit.

The adapter uses local deterministic lexical hashing embeddings by default. This keeps the benchmark self-contained and avoids depending on hosted embedding APIs. The result is therefore a benchmark of Antfly storage/index/query behavior inside MTCB’s scoring loop, not a claim about a production embedding model.

Profiles

  • smoke: one nano dataset, currently nano-macha, intended to validate adapter wiring and artifact shape.
  • nano / honed: three nano datasets, currently nano-macha, nano-sencha, and nano-hojicha, intended to produce a small but real retrieval result.

The adapter reports Recall@k, Precision@k, MRR@k, and NDCG@k for each dataset, plus mean metrics across datasets. It also recomputes mean Recall@k from the per-dataset rows and marks the run failed if the recomputed value diverges from MTCB’s BenchmarkResult.

Runtime Pin

The benchmark should be run against Antfly 0.2.0-rc.17 for the current Bastille result. The run artifact records the Antfly URL and best-effort runtime version endpoint response. The local harness can use ANTFLY_BIN to point at a specific prebuilt runtime; no Zig build should be triggered by this benchmark.

Caveats

MTCB’s public examples usually use neural embedding models such as Voyage. The current Antfly adapter deliberately uses local hashing embeddings to make the benchmark repeatable without credentials or model downloads. Before making a leaderboard-style quality claim, rerun the adapter with a documented production embedding model and compare against MTCB’s original in-memory vector store using the same chunks and embeddings.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
vi

rag-browsecomp-plus

missing

BrowseComp Plus

Fixed-budget native-hybrid retrieval over the BrowseComp-Plus evaluation set.

Methodology scope · protocol · interpretation

Agent Retrieval Cost harness

Measures what it actually costs an agent to answer questions over a large fixed corpus with different retrieval tooling. Quality (answer accuracy) is reported alongside cost; cost is the story: total LLM tokens, USD, wall time, and tool calls per query.

BrowseComp-Plus native-hybrid honed lane

bcp_native_hybrid/ is the publication lane for the four existing products that expose a genuinely native hybrid request: Antfly, Elasticsearch, Weaviate, and Milvus. PgVector and Chroma are excluded because their current harness paths are dense-only; adding those paths would change the retrieval contract. The separate lexical/TREC adapter is diagnostic and is not consumed by the publication page.

The checked bcp_native_hybrid/panel.json freezes 50 seed-17 development queries and their disjoint 780-query complement. The development panel is used only to warm memory lifecycles. Luna, through pinned pi 0.73.1, answers every held-out query against every backend: 3,120 evaluated query cells. Each cell uses the official Qwen3-Embedding-8B vectors and query prefix, the upstream QUERY_TEMPLATE_NO_GET_DOCUMENT, one search(query) tool, top five results, 512 Qwen3-0.6B snippet tokens, and the checked turn/token ceilings. Harbor supervises the Luna process without adding shell, filesystem, browser, or document-fetch tools.

Query publication evidence is resumed one backend/query cell at a time through the generic Circus publication cache. An exact hit includes the normalized trajectory, raw pi trajectory and stderr, Luna final record, Harbor result, complete Qwen3-32B judgement, original timestamps, and receipt. Corpus, vector, prompt, client, model, judge, backend, and Antfly-subject identities are part of the key. Incorrect answers and complete no-search outcomes are measured evidence; no-search always forces protocol correctness false. Crashes, partial trajectories, missing or unparseable judgements, and setup failures never hit. Database volumes, indexes, downloads, and memory measurements are never cached. First qualifying cache evidence wins under the generic cache policy. Fresh promotion also requires the operator’s explicit CIRCUS_QUIET_HOST_READY=1 assertion, retained as quiet-host.json.

The checked four-shard Latin-square schedule gives each backend every execution position once while still running all 780 held-out queries per backend. Only one backend stack is resident at a time. Every backend also receives exactly three deliberately fresh cgroup-v2 whole-stack memory lifecycles. Sampling starts before launch and covers prelaunch, service-launch, ingest, readiness, warm-query, and post-warm-idle. Publication memory is the warm-query anon + shmem peak mean and range; lifecycle demand, memory.current, kernel peaks, disk, events, images, logs, and raw timelines remain retained diagnostics. Swap, failed samples, incomplete phases, reused storage, or fewer than three trials rejects the report.

The report publishes per-backend correct count, accuracy with Wilson 95% interval, evidence recall, search/input/total-token distributions, completion, zero-search, and cached/fresh counts. Antfly-minus-peer paired accuracy and evidence-recall differences use the named paired-score mean ± 1.959963984540054 standard-error interval. These intervals are descriptive; no comparative acceptance threshold or automatic editorial selection is applied. Agent and judge wall time is network-bound diagnostic telemetry, not a latency claim.

From the repository root:

make browsecomp-native-hybrid-prepare
make browsecomp-native-hybrid-smoke
make browsecomp-native-hybrid-honed
make browsecomp-native-hybrid-report

The honed command writes strict summary.json, summary.md, detailed.json, raw runs/evals, cache references, memory timelines, and receipt.json to $BASTILLE_OUT/data/rag-browsecomp-plus/.

Design: trust through off-the-shelf parts

  • Agent: pi, an independent off-the-shelf coding agent (tools: read/write/edit/bash), run headless.
  • Orchestration: Harbor (the Terminal-Bench 2.0 harness, pinned version in the root Makefile) using Harbor’s first-party pi agent adapter (harbor run -a pi).
  • Antfly authors only the environments and the report. There is no bespoke agent loop; per-query tokens and USD cost come from pi’s own session accounting (message_end usage events in /logs/agent/pi.txt), parsed the same way Harbor itself does, not from our instrumentation.

One Harbor task per (tooling x question); one pi session per question; session totals are the per-query metrics.

Dataset

BrowseComp-Plus (Tevatron/browsecomp-plus): 100,195-document corpus, 830 queries with gold answers, cached at .data/browsecomp-plus/ by the BrowseComp-Plus harness. Questions are deliberately hard deep-research puzzles; absolute accuracy is expected to be low for every tooling. v1 applies no quality bar — accuracy is reported next to cost.

Fairness rules

  • Same questions for every tooling: one seed-17 pool of 200 query ids, sampled once; every run size is a prefix (probe 10 ⊂ default 50 ⊂ publish 200).
  • Same corpus surface: identical document text, capped at ARC_DOC_CHARS (default 20,000 chars/doc), in every store.
  • Same agent, same model (default openai-codex/gpt-5.6-luna, run on a ChatGPT subscription), same instruction contract; only the tooling cheat-sheet section differs.
  • Setup is performed by the harness, deterministically, before agent runs; setup wall time is reported in its own table and never billed to per-query cost. (Agent-performed setup is the separate agent-effort suite.)
  • The judge (default openai/gpt-4.1, same prompt as the BrowseComp-Plus answer eval) grades answers offline; judge spend is reported separately and never added to a row’s cost. Failed/unanswered queries count as incorrect.
  • Egress is audited, not firewalled: pi needs openrouter.ai, so containers have network access. The instruction forbids internet use, pi has no web tool, and the harvester scans every bash tool call for non-local hosts and flags suspect_egress per record (surfaced in the run-health table). A proxy allowlist is future work.

Toolings

RowSurface in the container
grepraw corpus as 100 JSONL shards at /corpus/, ripgrep installed
sqliteprebuilt FTS5 database at /corpus/corpus.fts5.db, sqlite3 CLI
antflyHTTP endpoint (host make start-zig, port 28080), BM25 full-text table
elasticsearchHTTP endpoint (elasticsearch_bench container), BM25 index
pgvector / milvus / weaviate / chromavector search over shared bge-small-en-v1.5 embeddings + a query-time embed endpoint (phase 3)

Running

Everything is driven from the repo root Makefile:

make agent-retrieval-cost-setup    # venv + harbor patch + base images + ingest (timed)
make agent-retrieval-cost-smoke    # free, offline: templates + parser fixture + report
make agent-retrieval-cost-probe    # paid: 10 questions x grep,sqlite,antfly
make agent-retrieval-cost-honed    # paid: ARC_SAMPLE (50) x ARC_TOOLINGS
make agent-retrieval-cost-judge    # paid: offline judge pass over harvested records
make agent-retrieval-cost-report   # free: agent-summary.json + summary.md

Knobs: ARC_MODEL, ARC_JUDGE_MODEL, ARC_SAMPLE, ARC_TOOLINGS, ARC_CONCURRENCY, ARC_ROW_CONCURRENCY, ARC_DOC_CHARS, ARC_AGENT_TIMEOUT (uniform per-task agent timeout, default 1800 s — the same for every tooling so wall/cost comparisons stay fair), ARC_RUN_ID. The OpenRouter key (used by the offline judge) is read from the process environment, the legacy agent_retrieval_cost.env, or pi’s private ~/.pi/agent/auth.json. The key is never copied into the repository.

Full 830-question checkpointed run

The full lane uses the seven validated surfaces (grep, sqlite, antfly, elasticsearch, pgvector, chroma, and antfly_hybrid) and the pinned v0.2.0-rc.20 ReleaseFast subject manifest. It is cohort-driven: 33 cohorts contain 25 questions and the final cohort contains five. Every cohort is paired across all seven rows, and one command invocation runs at most one cohort.

make agent-retrieval-cost-full-prepare  # dataset, stores, immutable manifest
make agent-retrieval-cost-full-canary   # one question x seven rows
make agent-retrieval-cost-full-next     # one 25-question paired cohort
make agent-retrieval-cost-full-drain    # repeat cohorts; stop on first safety pause
make agent-retrieval-cost-full-status   # no model calls

full-drain is only a checkpoint supervisor: it invokes the same one-cohort lane repeatedly, reruns every preflight before advancing, and exits immediately if an attempt is paused or fails. It does not weaken the per-cohort cost, auth, disk, service, or retry protections.

full-run-manifest.json freezes question order, cohort boundaries, models, toolings, and subject hashes. full-run-ledger.json records immutable attempts. Harvest merges by (tooling, query_id), refuses to overwrite a final cell, and only replaces explicit authentication, rate-limit, or infrastructure failures. Completed cells therefore survive an outage and are skipped on resume.

The preflight requires all stores to report 100,195 indexed documents, a ready and fully query-visible Antfly vector index, at least 30 GB free, and at least two hours of OAuth validity. It warns at $550 and refuses to launch a new cohort at $650 of API-equivalent Luna usage. The incremental OpenRouter judge has a separate $5 actual-spend hard cap. Subscription agent spend remains $0 incremental; equivalent cost is an analysis yardstick, not a cash charge.

Partial reports contain only fully paired questions. Reports include the accuracy-vs-budget curve with bootstrap intervals, a cost-vs-quality scatter/Pareto chart, cost per correct answer, payload volume, command errors, and evidence-to-first-hit diagnostics. Raw de-obfuscated questions and document content remain local and must not be pasted into public summaries.

Rows run through a bounded scheduler. The default is two Harbor rows in parallel (ARC_ROW_CONCURRENCY=2), with four concurrent trials in each row (ARC_CONCURRENCY=4): at most eight subscription agents at once. The 50×7 RF335 run’s observed row durations project to roughly 95 minutes of inference at this setting instead of 172 minutes sequentially. Parallel rows share host resources, so wall-time comparisons should be treated as contention-sensitive; token, cost, and accuracy metrics remain per isolated trial. Set ARC_ROW_CONCURRENCY=1 to reproduce the old sequential schedule.

Model auth

The agent model defaults to openai-codex/gpt-5.6-luna — GPT-5.6 Luna run on a ChatGPT Plus/Pro subscription via pi’s Codex OAuth provider. One-time setup: run pi interactively, /login, and pick “ChatGPT Plus/Pro (Codex)” to complete the browser OAuth. That writes ~/.pi/agent/auth.json, which the harness bind-mounts read-only into every trial container (--mounts). The run preflight refuses to start if that file is empty.

Because a subscription is flat-rate, pi reports token counts but $0 cost, so $/query is computed from token counts at published Luna rates ($1/$6/$0.10 per 1M in/out/cached-read) and each record is tagged cost_source: price_table_estimate. See arc/pricing.py. Pass a different ARC_MODEL (e.g. openai/gpt-5.6-luna with OPENAI_API_KEY, or openrouter/...) to use real per-token billing instead; pi’s own cost_usd is then used and tagged pi_usage.

Note: Codex OAuth access tokens expire in hours. For long matrix runs, log in (or refresh) shortly before starting; the read-only mount can’t refresh mid-run.

Outputs

Under $BASTILLE_OUT/data/agent-retrieval-cost/:

  • <tooling>/records.jsonl — one record per (tooling, query): status, answer, gold, tokens {input, output, cache_read, cache_write, total}, cost_usd (pi’s own accounting), wall_seconds (first-to-last session event; excludes image build and pi install), tool_calls, suspect_egress, judge verdict.
  • agent-summary.json, setup-summary.json, judge-summary.json, summary.md (per-query means, setup table, cumulative cost, run health).

Caveats

  • Wall/query depends on host load and provider latency at run time; treat it as indicative, not a latency benchmark.
  • Timed-out and provider-errored trials (e.g. OpenRouter routes occasionally return content_filter mid-run) count as incorrect and stay in the denominator; the run-health table reports them per row.
  • pi is installed per trial by Harbor’s adapter (npm install -g ...@latest); the base image pre-installs node+pi so this is fast, but pi’s version floats with the run date and is recorded in /etc/arc-pi-version in the image.
  • Harbor’s old upload_dir docker-cp bug (verifier tests landing at /tests/tests/) is fixed upstream in the pinned version; patches/apply_harbor_upload_dir_patch.py verifies this and can patch the legacy layout if the pin ever moves backwards.
  • Vector rows share one embedding model and code path (ingest == query-time); engines’ native embedding pipelines are intentionally not used.
Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
vii

agent-retrieval-cost

missing

Agent retrieval cost

Retrieval quality and resource cost for agent-oriented search workflows.

Methodology scope · protocol · interpretation

Agent Retrieval Cost harness

Measures what it actually costs an agent to answer questions over a large fixed corpus with different retrieval tooling. Quality (answer accuracy) is reported alongside cost; cost is the story: total LLM tokens, USD, wall time, and tool calls per query.

BrowseComp-Plus native-hybrid honed lane

bcp_native_hybrid/ is the publication lane for the four existing products that expose a genuinely native hybrid request: Antfly, Elasticsearch, Weaviate, and Milvus. PgVector and Chroma are excluded because their current harness paths are dense-only; adding those paths would change the retrieval contract. The separate lexical/TREC adapter is diagnostic and is not consumed by the publication page.

The checked bcp_native_hybrid/panel.json freezes 50 seed-17 development queries and their disjoint 780-query complement. The development panel is used only to warm memory lifecycles. Luna, through pinned pi 0.73.1, answers every held-out query against every backend: 3,120 evaluated query cells. Each cell uses the official Qwen3-Embedding-8B vectors and query prefix, the upstream QUERY_TEMPLATE_NO_GET_DOCUMENT, one search(query) tool, top five results, 512 Qwen3-0.6B snippet tokens, and the checked turn/token ceilings. Harbor supervises the Luna process without adding shell, filesystem, browser, or document-fetch tools.

Query publication evidence is resumed one backend/query cell at a time through the generic Circus publication cache. An exact hit includes the normalized trajectory, raw pi trajectory and stderr, Luna final record, Harbor result, complete Qwen3-32B judgement, original timestamps, and receipt. Corpus, vector, prompt, client, model, judge, backend, and Antfly-subject identities are part of the key. Incorrect answers and complete no-search outcomes are measured evidence; no-search always forces protocol correctness false. Crashes, partial trajectories, missing or unparseable judgements, and setup failures never hit. Database volumes, indexes, downloads, and memory measurements are never cached. First qualifying cache evidence wins under the generic cache policy. Fresh promotion also requires the operator’s explicit CIRCUS_QUIET_HOST_READY=1 assertion, retained as quiet-host.json.

The checked four-shard Latin-square schedule gives each backend every execution position once while still running all 780 held-out queries per backend. Only one backend stack is resident at a time. Every backend also receives exactly three deliberately fresh cgroup-v2 whole-stack memory lifecycles. Sampling starts before launch and covers prelaunch, service-launch, ingest, readiness, warm-query, and post-warm-idle. Publication memory is the warm-query anon + shmem peak mean and range; lifecycle demand, memory.current, kernel peaks, disk, events, images, logs, and raw timelines remain retained diagnostics. Swap, failed samples, incomplete phases, reused storage, or fewer than three trials rejects the report.

The report publishes per-backend correct count, accuracy with Wilson 95% interval, evidence recall, search/input/total-token distributions, completion, zero-search, and cached/fresh counts. Antfly-minus-peer paired accuracy and evidence-recall differences use the named paired-score mean ± 1.959963984540054 standard-error interval. These intervals are descriptive; no comparative acceptance threshold or automatic editorial selection is applied. Agent and judge wall time is network-bound diagnostic telemetry, not a latency claim.

From the repository root:

make browsecomp-native-hybrid-prepare
make browsecomp-native-hybrid-smoke
make browsecomp-native-hybrid-honed
make browsecomp-native-hybrid-report

The honed command writes strict summary.json, summary.md, detailed.json, raw runs/evals, cache references, memory timelines, and receipt.json to $BASTILLE_OUT/data/rag-browsecomp-plus/.

Design: trust through off-the-shelf parts

  • Agent: pi, an independent off-the-shelf coding agent (tools: read/write/edit/bash), run headless.
  • Orchestration: Harbor (the Terminal-Bench 2.0 harness, pinned version in the root Makefile) using Harbor’s first-party pi agent adapter (harbor run -a pi).
  • Antfly authors only the environments and the report. There is no bespoke agent loop; per-query tokens and USD cost come from pi’s own session accounting (message_end usage events in /logs/agent/pi.txt), parsed the same way Harbor itself does, not from our instrumentation.

One Harbor task per (tooling x question); one pi session per question; session totals are the per-query metrics.

Dataset

BrowseComp-Plus (Tevatron/browsecomp-plus): 100,195-document corpus, 830 queries with gold answers, cached at .data/browsecomp-plus/ by the BrowseComp-Plus harness. Questions are deliberately hard deep-research puzzles; absolute accuracy is expected to be low for every tooling. v1 applies no quality bar — accuracy is reported next to cost.

Fairness rules

  • Same questions for every tooling: one seed-17 pool of 200 query ids, sampled once; every run size is a prefix (probe 10 ⊂ default 50 ⊂ publish 200).
  • Same corpus surface: identical document text, capped at ARC_DOC_CHARS (default 20,000 chars/doc), in every store.
  • Same agent, same model (default openai-codex/gpt-5.6-luna, run on a ChatGPT subscription), same instruction contract; only the tooling cheat-sheet section differs.
  • Setup is performed by the harness, deterministically, before agent runs; setup wall time is reported in its own table and never billed to per-query cost. (Agent-performed setup is the separate agent-effort suite.)
  • The judge (default openai/gpt-4.1, same prompt as the BrowseComp-Plus answer eval) grades answers offline; judge spend is reported separately and never added to a row’s cost. Failed/unanswered queries count as incorrect.
  • Egress is audited, not firewalled: pi needs openrouter.ai, so containers have network access. The instruction forbids internet use, pi has no web tool, and the harvester scans every bash tool call for non-local hosts and flags suspect_egress per record (surfaced in the run-health table). A proxy allowlist is future work.

Toolings

RowSurface in the container
grepraw corpus as 100 JSONL shards at /corpus/, ripgrep installed
sqliteprebuilt FTS5 database at /corpus/corpus.fts5.db, sqlite3 CLI
antflyHTTP endpoint (host make start-zig, port 28080), BM25 full-text table
elasticsearchHTTP endpoint (elasticsearch_bench container), BM25 index
pgvector / milvus / weaviate / chromavector search over shared bge-small-en-v1.5 embeddings + a query-time embed endpoint (phase 3)

Running

Everything is driven from the repo root Makefile:

make agent-retrieval-cost-setup    # venv + harbor patch + base images + ingest (timed)
make agent-retrieval-cost-smoke    # free, offline: templates + parser fixture + report
make agent-retrieval-cost-probe    # paid: 10 questions x grep,sqlite,antfly
make agent-retrieval-cost-honed    # paid: ARC_SAMPLE (50) x ARC_TOOLINGS
make agent-retrieval-cost-judge    # paid: offline judge pass over harvested records
make agent-retrieval-cost-report   # free: agent-summary.json + summary.md

Knobs: ARC_MODEL, ARC_JUDGE_MODEL, ARC_SAMPLE, ARC_TOOLINGS, ARC_CONCURRENCY, ARC_ROW_CONCURRENCY, ARC_DOC_CHARS, ARC_AGENT_TIMEOUT (uniform per-task agent timeout, default 1800 s — the same for every tooling so wall/cost comparisons stay fair), ARC_RUN_ID. The OpenRouter key (used by the offline judge) is read from the process environment, the legacy agent_retrieval_cost.env, or pi’s private ~/.pi/agent/auth.json. The key is never copied into the repository.

Full 830-question checkpointed run

The full lane uses the seven validated surfaces (grep, sqlite, antfly, elasticsearch, pgvector, chroma, and antfly_hybrid) and the pinned v0.2.0-rc.20 ReleaseFast subject manifest. It is cohort-driven: 33 cohorts contain 25 questions and the final cohort contains five. Every cohort is paired across all seven rows, and one command invocation runs at most one cohort.

make agent-retrieval-cost-full-prepare  # dataset, stores, immutable manifest
make agent-retrieval-cost-full-canary   # one question x seven rows
make agent-retrieval-cost-full-next     # one 25-question paired cohort
make agent-retrieval-cost-full-drain    # repeat cohorts; stop on first safety pause
make agent-retrieval-cost-full-status   # no model calls

full-drain is only a checkpoint supervisor: it invokes the same one-cohort lane repeatedly, reruns every preflight before advancing, and exits immediately if an attempt is paused or fails. It does not weaken the per-cohort cost, auth, disk, service, or retry protections.

full-run-manifest.json freezes question order, cohort boundaries, models, toolings, and subject hashes. full-run-ledger.json records immutable attempts. Harvest merges by (tooling, query_id), refuses to overwrite a final cell, and only replaces explicit authentication, rate-limit, or infrastructure failures. Completed cells therefore survive an outage and are skipped on resume.

The preflight requires all stores to report 100,195 indexed documents, a ready and fully query-visible Antfly vector index, at least 30 GB free, and at least two hours of OAuth validity. It warns at $550 and refuses to launch a new cohort at $650 of API-equivalent Luna usage. The incremental OpenRouter judge has a separate $5 actual-spend hard cap. Subscription agent spend remains $0 incremental; equivalent cost is an analysis yardstick, not a cash charge.

Partial reports contain only fully paired questions. Reports include the accuracy-vs-budget curve with bootstrap intervals, a cost-vs-quality scatter/Pareto chart, cost per correct answer, payload volume, command errors, and evidence-to-first-hit diagnostics. Raw de-obfuscated questions and document content remain local and must not be pasted into public summaries.

Rows run through a bounded scheduler. The default is two Harbor rows in parallel (ARC_ROW_CONCURRENCY=2), with four concurrent trials in each row (ARC_CONCURRENCY=4): at most eight subscription agents at once. The 50×7 RF335 run’s observed row durations project to roughly 95 minutes of inference at this setting instead of 172 minutes sequentially. Parallel rows share host resources, so wall-time comparisons should be treated as contention-sensitive; token, cost, and accuracy metrics remain per isolated trial. Set ARC_ROW_CONCURRENCY=1 to reproduce the old sequential schedule.

Model auth

The agent model defaults to openai-codex/gpt-5.6-luna — GPT-5.6 Luna run on a ChatGPT Plus/Pro subscription via pi’s Codex OAuth provider. One-time setup: run pi interactively, /login, and pick “ChatGPT Plus/Pro (Codex)” to complete the browser OAuth. That writes ~/.pi/agent/auth.json, which the harness bind-mounts read-only into every trial container (--mounts). The run preflight refuses to start if that file is empty.

Because a subscription is flat-rate, pi reports token counts but $0 cost, so $/query is computed from token counts at published Luna rates ($1/$6/$0.10 per 1M in/out/cached-read) and each record is tagged cost_source: price_table_estimate. See arc/pricing.py. Pass a different ARC_MODEL (e.g. openai/gpt-5.6-luna with OPENAI_API_KEY, or openrouter/...) to use real per-token billing instead; pi’s own cost_usd is then used and tagged pi_usage.

Note: Codex OAuth access tokens expire in hours. For long matrix runs, log in (or refresh) shortly before starting; the read-only mount can’t refresh mid-run.

Outputs

Under $BASTILLE_OUT/data/agent-retrieval-cost/:

  • <tooling>/records.jsonl — one record per (tooling, query): status, answer, gold, tokens {input, output, cache_read, cache_write, total}, cost_usd (pi’s own accounting), wall_seconds (first-to-last session event; excludes image build and pi install), tool_calls, suspect_egress, judge verdict.
  • agent-summary.json, setup-summary.json, judge-summary.json, summary.md (per-query means, setup table, cumulative cost, run health).

Caveats

  • Wall/query depends on host load and provider latency at run time; treat it as indicative, not a latency benchmark.
  • Timed-out and provider-errored trials (e.g. OpenRouter routes occasionally return content_filter mid-run) count as incorrect and stay in the denominator; the run-health table reports them per row.
  • pi is installed per trial by Harbor’s adapter (npm install -g ...@latest); the base image pre-installs node+pi so this is fast, but pi’s version floats with the run date and is recorded in /etc/arc-pi-version in the image.
  • Harbor’s old upload_dir docker-cp bug (verifier tests landing at /tests/tests/) is fixed upstream in the pinned version; patches/apply_harbor_upload_dir_patch.py verifies this and can patch the legacy layout if the pin ever moves backwards.
  • Vector rows share one embedding model and code path (ingest == query-time); engines’ native embedding pipelines are intentionally not used.
Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject
viii

office-qa-pro

missing

OfficeQA Pro

Raw-document ingestion, retrieval, and question answering over the OfficeQA-Pro corpus.

Methodology scope · protocol · interpretation

OfficeQA-Pro raw-PDF benchmark

This harness measures the complete path from 697 Treasury Bulletin PDFs to an agent’s final answer. The headline comparison is ingestion complexity and cold setup time; answer accuracy and agent cost are measured on the same seeded OfficeQA-Pro questions after each index is ready.

The default matrix is 133 questions per row with seed 17:

RowSourceExtraction and retrieval
antfly_native_hybridRaw PDFsAntfly PDF extraction/OCR, chunking, embedding, lexical + vector index
docling_pgvectorRaw PDFsDocling standard OCR + accurate tables, BGE chunks/embeddings, pgvector HNSW
docling_elasticsearchRaw PDFsThe same Docling chunks, Elasticsearch BM25
docling_sqliteRaw PDFsThe same Docling chunks, SQLite FTS5
oracle_pgvectorPublisher transformed textClearly labeled extraction ceiling, BGE + pgvector HNSW

The three Docling rows share one extraction pass. The oracle files never enter a raw-PDF row. Questions given to agents contain neither source_files hints nor gold answers.

Prerequisites

  • Docker, uv, Go, and enough disk for the 4 GB corpus plus derived indexes.
  • Hugging Face access accepted for the gated databricks/officeqa dataset and HF_TOKEN exported for the explicit download step.
  • pi logged into ChatGPT (pi, then /login) for the default openai-codex/gpt-5.6-luna agent.
  • A ReleaseFast Antfly binary. Override the suite default with ANTFLY_BIN=/absolute/path/to/antfly.

The Antfly qualification deliberately includes one scanned and one born-digital PDF. Run it before committing to the corpus-wide ingest. Current Antfly source needs to render the requested PDF page to PNG before sending it to the local Florence reader; passing the PDF URL directly is not supported by that reader. docsaf sync --help also needs to show the --ocr* options.

Only rebuild Antfly after checking those help texts and qualifying the binary. On this machine a full Zig build may run out of memory, so warn and get explicit approval first, then constrain parallelism:

cd /path/to/antfly/zig
zig build lib-pdf-test -j1
zig build lib-db-test -j1 -- --test-filter 'document OCR media parts'
zig build install -Dedition=full -Doptimize=ReleaseFast -j1

Run sequence

make targets live at the antfly-circus repository root.

make office-qa-pro-smoke
make office-qa-pro-setup
make office-qa-pro-download

# Before the large ingest:
ANTFLY_BIN=/path/to/antfly make office-qa-pro-qualify-antfly

# Paid 10-question, three-row end-to-end probe:
ANTFLY_BIN=/path/to/antfly make office-qa-pro-probe

# Paid Pro-133, five-row matrix:
ANTFLY_BIN=/path/to/antfly make office-qa-pro-honed

office-qa-pro-honed refuses to download data implicitly. It starts only the services selected by OQA_TOOLINGS, performs a cold setup, generates identical seeded tasks, runs Harbor/pi at OQA_CONCURRENCY=4, harvests, deterministically scores, and writes the report. Useful overrides include:

make office-qa-pro-honed \
  OQA_SAMPLE=20 \
  OQA_TOOLINGS=docling_pgvector,docling_sqlite \
  OQA_CONCURRENCY=2

Measurement and scoring

Downloads and model-cache warmup are excluded from setup timing. Setup begins with local source files and cached models; each recorded stage and total wall time is written to setup-summary.json. The raw-PDF rows include extraction, OCR, chunking, embedding where applicable, and indexing.

The scorer is reward.py pinned to OfficeQA commit 86753108d69e149cc28abd346bb8c3ca1cbfc7cf. It is applied to the final answer and every running best guess at exact, 0.1%, 1%, and 5% relative tolerance. The primary metric is accuracy at 1%; no LLM judge is used.

Agent accounting is inherited from the ARC harness: input/cache/output tokens, price-table-equivalent USD, wall time, tool calls, answer trajectory, and cost to the first answer that remains correct. Results land under results/benchmark-page/manual/data/office-qa-pro/ by default.

Planning estimate

The full default run is 665 trials (133 questions × 5 rows). Existing local ARC Luna trials average about $0.42 price-table-equivalent and 138 seconds of total trial wall time. That gives a lower-bound query phase of roughly $280 and 6.4 hours at concurrency four. OfficeQA is likely to require longer investigation, so budget approximately $300–$600 equivalent and 7–12 hours for agent trials. The default model uses a ChatGPT subscription, so this is benchmark accounting, not necessarily an incremental API invoice, but it will consume subscription capacity.

The larger uncertainty is cold ingestion of about 89,000 PDF pages with CPU/local ML OCR. Until the two-PDF qualification and a small corpus timing are measured, allow roughly 2–6 elapsed days end to end, of which most is Antfly and Docling extraction/OCR. The 10-question probe should be used to replace this range with measured throughput before launching Pro-133.

Evidence status availability · expected contract

Why this lane has no selected measurement

No reviewed benchmark result is selected for this subject.

Expected
Reviewed aggregate with a validation receipt
Observed
No result selected for this subject