elips/docs
Practice

Performance

What to measure

Three numbers carry most decisions: recall@k against an exact baseline, p95 query latency at your real top-k, and write throughput at your real batch size. Anything else is downstream of these.

bash
elips bench /tmp/bench_db --count 100000 --dim 128

For reference, the shipped benchmark on an Apple M4 (dim 128, nb 100000, nq 1000, k 10, L2, ELIPS 1.1.0):

ConfigurationRecall@10QPS
IndexFlat (CPU)1.000489
bf_knn (Metal, batched)1.000914
IndexIVFFlat nlist=316, nprobe=1280.8011616
IndexIVFFlat nlist=316, nprobe=80.15214123

nprobe is the recall/throughput dial: more probes recover recall, fewer trade it for speed.

Tuning HNSW

ParameterDefaultTrade-off
M32Higher → better recall, more memory.
ef_construction200Higher → better graph, slower writes.
ef_search64Higher → better recall, slower reads.

Use IndexFlat at the same query set as a ground-truth baseline when sweeping ef_search.

Plan for filters

Equality and set-membership predicates accelerate through MetadataIndex. When the candidate set is small enough the planner switches to exact_candidates — often faster than running ANN over the full population. Inspect with collection.explain.

Durability cost

paranoid calls fsync per write; throughput is bounded by your storage's sync rate. standard drops the fsync but keeps the flush. relaxed buffers and amortises at checkpoint — pick it when crash recovery to the most recent checkpoint is acceptable.

GPU batching

With ELIPS_GPU_ENABLED, the QueryBatcher coalesces concurrent queries into a single GPU launch. The payoff is large: on the Apple M4 reference above, bf_knn on Metal runs at 914 QPS when queries are batched but only 24 QPS issued one at a time. Increase the in-flight query window in your serving layer to give the batcher room to work; very low concurrency leaves the GPU under-fed.