Background
#853 (PR #854) removed every per-candidate hash probe from the HNSW graph traversal by moving it to segment-local ordinals. The Phase 0b prototype gate for that work measured the probe cost directly: swapping the pool doc_id → position maps from std HashMap (SipHash) to ahash::AHashMap improved the HNSW store-level deletion benches by −30/−32% before any structural change (gate record).
The Flat and IVF searchers were out of #853's scope and still pay that SipHash probe per scanned candidate:
flat/searcher.rs — the int8 hot path resolves pool.field_position_index(field_name) once, then probes the inner HashMap<u64, u32> per candidate inside the scan closure.
ivf/searcher.rs — parallel_scan over the probed clusters calls pool.get_record(*doc_id, field_name) per candidate, which probes the same map.
- Map definitions (inner maps are std
HashMap<u64, u32>): quantized_storage.rs, pq_storage.rs, pq_fastscan_storage.rs, rerank_storage.rs (field_index).
ahash is already a workspace dependency, and post-#853 the HNSW hot path no longer touches these maps at all — so the swap is low-risk and its benefit is confined to the Flat/IVF scan paths and cold lookups.
What to do
Swap the inner HashMap<u64, u32> (and the reader-side HashMap<u64, usize> prefetch map if convenient) to ahash::AHashMap in the four pool types, following the type through the few construction/return sites.
Acceptance criteria
References
Task list
Background
#853 (PR #854) removed every per-candidate hash probe from the HNSW graph traversal by moving it to segment-local ordinals. The Phase 0b prototype gate for that work measured the probe cost directly: swapping the pool
doc_id → positionmaps from stdHashMap(SipHash) toahash::AHashMapimproved the HNSW store-level deletion benches by −30/−32% before any structural change (gate record).The Flat and IVF searchers were out of #853's scope and still pay that SipHash probe per scanned candidate:
flat/searcher.rs— the int8 hot path resolvespool.field_position_index(field_name)once, then probes the innerHashMap<u64, u32>per candidate inside the scan closure.ivf/searcher.rs—parallel_scanover the probed clusters callspool.get_record(*doc_id, field_name)per candidate, which probes the same map.HashMap<u64, u32>):quantized_storage.rs,pq_storage.rs,pq_fastscan_storage.rs,rerank_storage.rs(field_index).ahashis already a workspace dependency, and post-#853 the HNSW hot path no longer touches these maps at all — so the swap is low-risk and its benefit is confined to the Flat/IVF scan paths and cold lookups.What to do
Swap the inner
HashMap<u64, u32>(and the reader-sideHashMap<u64, usize>prefetch map if convenient) toahash::AHashMapin the four pool types, following the type through the few construction/return sites.Acceptance criteria
Flat Search,Flat Search int8 kernel,IVF Search,Flat/IVF Filtered Allowset), with the usual A/A null-pair disciplineDeletion Search,HNSW Graph Search sparse_ids) — expected neutral since perf(vector/hnsw): segment-local u32 ordinal graph + LVS1 v2 format (sub-issue of #686) #853 removed those probesReferences
Task list