diff --git a/lib/segment/src/index/hnsw_index/graph_layers.rs b/lib/segment/src/index/hnsw_index/graph_layers.rs index 92106a276f..53c0e83ee0 100644 --- a/lib/segment/src/index/hnsw_index/graph_layers.rs +++ b/lib/segment/src/index/hnsw_index/graph_layers.rs @@ -98,7 +98,6 @@ pub trait GraphLayersBase { level: usize, ef: usize, points_scorer: &mut FilteredScorer, - existing_links: &[PointOffsetType], ) -> FixedLengthPriorityQueue { let mut visited_list = self.get_visited_list_from_pool(); visited_list.check_and_update_visited(level_entry.idx); @@ -106,15 +105,6 @@ pub trait GraphLayersBase { self._search_on_level(&mut search_context, level, &mut visited_list, points_scorer); - for &existing_link in existing_links { - if !visited_list.check(existing_link) { - search_context.process_candidate(ScoredPointOffset { - idx: existing_link, - score: points_scorer.score_point(existing_link), - }); - } - } - self.return_visited_list_to_pool(visited_list); search_context.nearest } @@ -215,8 +205,7 @@ impl GraphLayers { &mut points_scorer, ); - let nearest = - self.search_on_level(zero_level_entry, 0, max(top, ef), &mut points_scorer, &[]); + let nearest = self.search_on_level(zero_level_entry, 0, max(top, ef), &mut points_scorer); nearest.into_iter().take(top).collect_vec() } @@ -367,7 +356,6 @@ mod tests { 0, 32, &mut scorer, - &[], ); assert_eq!(nearest_on_level.len(), graph_links[0][0].len() + 1); diff --git a/lib/segment/src/index/hnsw_index/graph_layers_builder.rs b/lib/segment/src/index/hnsw_index/graph_layers_builder.rs index c8886333f4..96140db289 100644 --- a/lib/segment/src/index/hnsw_index/graph_layers_builder.rs +++ b/lib/segment/src/index/hnsw_index/graph_layers_builder.rs @@ -13,6 +13,7 @@ use crate::index::hnsw_index::entry_points::EntryPoints; use crate::index::hnsw_index::graph_layers::{GraphLayers, GraphLayersBase, LinkContainer}; use crate::index::hnsw_index::graph_links::GraphLinksConverter; use crate::index::hnsw_index::point_scorer::FilteredScorer; +use crate::index::hnsw_index::search_context::SearchContext; use crate::index::visited_pool::{VisitedList, VisitedPool}; use crate::spaces::tools::FixedLengthPriorityQueue; use crate::types::{PointOffsetType, ScoreType}; @@ -282,6 +283,34 @@ impl GraphLayersBuilder { result_list } + fn search_existing_point_on_level( + &self, + level_entry: ScoredPointOffset, + level: usize, + ef: usize, + points_scorer: &mut FilteredScorer, + point_id: PointOffsetType, + ) -> FixedLengthPriorityQueue { + let mut visited_list = self.get_visited_list_from_pool(); + visited_list.check_and_update_visited(level_entry.idx); + let mut search_context = SearchContext::new(level_entry, ef); + + self._search_on_level(&mut search_context, level, &mut visited_list, points_scorer); + + let existing_links = self.links_layers[point_id as usize][level].read(); + for &existing_link in existing_links.iter() { + if !visited_list.check(existing_link) { + search_context.process_candidate(ScoredPointOffset { + idx: existing_link, + score: points_scorer.score_point(existing_link), + }); + } + } + + self.return_visited_list_to_pool(visited_list); + search_context.nearest + } + /// fn select_candidates_with_heuristic( candidates: FixedLengthPriorityQueue, @@ -339,14 +368,12 @@ impl GraphLayersBuilder { let level_m = self.get_m(curr_level); let nearest_points = { - let existing_links = - self.links_layers[point_id as usize][curr_level].read(); - self.search_on_level( + self.search_existing_point_on_level( level_entry, curr_level, self.ef_construct, &mut points_scorer, - &existing_links, + point_id, ) }; diff --git a/lib/segment/src/index/hnsw_index/tests/test_compact_graph_layer.rs b/lib/segment/src/index/hnsw_index/tests/test_compact_graph_layer.rs index 3391390451..45f3e80505 100644 --- a/lib/segment/src/index/hnsw_index/tests/test_compact_graph_layer.rs +++ b/lib/segment/src/index/hnsw_index/tests/test_compact_graph_layer.rs @@ -34,8 +34,7 @@ fn search_in_builder( &mut points_scorer, ); - let nearest = - builder.search_on_level(zero_level_entry, 0, max(top, ef), &mut points_scorer, &[]); + let nearest = builder.search_on_level(zero_level_entry, 0, max(top, ef), &mut points_scorer); nearest.into_iter().take(top).collect_vec() }