Skip to content

Commit ea2f707

Browse files
committed
feat: refine HNSW greedy search by adjusting history buffer capacity, increasing max iterations, and improving early termination logic.
1 parent 492c434 commit ea2f707

1 file changed

Lines changed: 11 additions & 12 deletions

File tree

src/apps/hnsw/partition/search.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -645,13 +645,14 @@ impl HnswOnlinePartition {
645645

646646
//println!("Starting search with vertex: {:?}", starting_vertices);
647647
// CRITICAL: Always start with a fresh visited set for each new search
648+
let history_capacity = std::cmp::max(1, std::cmp::max(ef, k)).next_power_of_two();
648649
let partition_search = PartitionSearch {
649650
schema,
650651
field_id,
651652
metadata: SearchMetadata {
652653
level: max_level,
653654
visited: CompactVisitedSet::with_capacity(ef * 10),
654-
history: RingBuffer::new(k.next_power_of_two()),
655+
history: RingBuffer::new(history_capacity),
655656
remote_frontiers: HashSet::with_hasher(IdBuildHasher),
656657
last_distance: Distance::INFINITY,
657658
level_entries: AHashMap::default(),
@@ -664,7 +665,7 @@ impl HnswOnlinePartition {
664665
frontier: starting_vertices,
665666
server_id: self.server_id,
666667
iteration: 0,
667-
history: RingBuffer::new(k.next_power_of_two()),
668+
history: RingBuffer::new(history_capacity),
668669
last_distance: Distance::INFINITY,
669670
metric,
670671
max_level,
@@ -1948,7 +1949,7 @@ impl HnswOnlinePartition {
19481949
const VERTICES_PER_ITERATION: usize = 4;
19491950

19501951
// Maximum iterations (safety limit, usually converges much faster)
1951-
let max_iterations = 50;
1952+
let max_iterations = 100;
19521953
let mut iterations = 0;
19531954

19541955
// Early termination tracking: stop when top-k results are stable
@@ -1977,7 +1978,7 @@ impl HnswOnlinePartition {
19771978
last_best_distance = current_best;
19781979

19791980
// Early termination: if best distance is stable for 3 iterations and we have enough candidates
1980-
if stable_count >= 3 && search.history.len() >= ef {
1981+
if stable_count >= 3 && search.history.len() >= ef && priority_frontier.len() >= ef {
19811982
break;
19821983
}
19831984

@@ -2025,15 +2026,13 @@ impl HnswOnlinePartition {
20252026

20262027
iterations += 1;
20272028

2028-
// Check if we have enough candidates
2029-
if search.history.len() >= ef
2030-
&& priority_frontier
2029+
if search.history.len() >= ef && priority_frontier.len() >= ef {
2030+
let frontier_best = priority_frontier
20312031
.peek_min_distance()
2032-
.unwrap_or(Distance::INFINITY)
2033-
> last_best_distance
2034-
{
2035-
// We have enough candidates and frontier has worse candidates, stop
2036-
break;
2032+
.unwrap_or(Distance::INFINITY);
2033+
if frontier_best > last_best_distance {
2034+
break;
2035+
}
20372036
}
20382037
}
20392038

0 commit comments

Comments
 (0)