mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-07-31 19:00:00 +00:00
Rewrite cheapest path algorithm and empty path cache
It is now much simpler and has much better performance.
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
|
||||
use rand::random;
|
||||
use roaring::RoaringBitmap;
|
||||
use std::fs::File;
|
||||
use std::time::Instant;
|
||||
use std::{io::Write, path::PathBuf};
|
||||
|
||||
use crate::new::ranking_rule_graph::typo::TypoGraph;
|
||||
@ -9,7 +11,7 @@ use crate::new::query_term::{LocatedQueryTerm, QueryTerm, WordDerivations};
|
||||
use crate::new::ranking_rule_graph::empty_paths_cache::EmptyPathsCache;
|
||||
use crate::new::ranking_rule_graph::{Edge, EdgeDetails, RankingRuleGraphTrait};
|
||||
use crate::new::ranking_rule_graph::{
|
||||
paths_map::PathsMap, proximity::ProximityGraph, RankingRuleGraph,
|
||||
proximity::ProximityGraph, RankingRuleGraph,
|
||||
};
|
||||
|
||||
use super::{RankingRule, SearchLogger};
|
||||
@ -19,14 +21,18 @@ pub enum SearchEvents {
|
||||
ranking_rule_idx: usize,
|
||||
query: QueryGraph,
|
||||
universe: RoaringBitmap,
|
||||
time: Instant,
|
||||
},
|
||||
RankingRuleNextBucket {
|
||||
ranking_rule_idx: usize,
|
||||
universe: RoaringBitmap,
|
||||
candidates: RoaringBitmap,
|
||||
time: Instant,
|
||||
},
|
||||
RankingRuleEndIteration {
|
||||
ranking_rule_idx: usize,
|
||||
universe: RoaringBitmap,
|
||||
time: Instant,
|
||||
},
|
||||
ExtendResults {
|
||||
new: Vec<u32>,
|
||||
@ -36,20 +42,27 @@ pub enum SearchEvents {
|
||||
},
|
||||
ProximityState {
|
||||
graph: RankingRuleGraph<ProximityGraph>,
|
||||
paths: PathsMap<u64>,
|
||||
paths: Vec<Vec<u32>>,
|
||||
empty_paths_cache: EmptyPathsCache,
|
||||
universe: RoaringBitmap,
|
||||
distances: Vec<Vec<u64>>,
|
||||
cost: u64,
|
||||
},
|
||||
TypoState {
|
||||
graph: RankingRuleGraph<TypoGraph>,
|
||||
paths: PathsMap<u64>,
|
||||
paths: Vec<Vec<u32>>,
|
||||
empty_paths_cache: EmptyPathsCache,
|
||||
universe: RoaringBitmap,
|
||||
distances: Vec<Vec<u64>>,
|
||||
cost: u64,
|
||||
},
|
||||
RankingRuleSkipBucket { ranking_rule_idx: usize, candidates: RoaringBitmap },
|
||||
RankingRuleSkipBucket { ranking_rule_idx: usize, candidates: RoaringBitmap, time: Instant, },
|
||||
}
|
||||
|
||||
pub struct DetailedSearchLogger {
|
||||
folder_path: PathBuf,
|
||||
initial_query: Option<QueryGraph>,
|
||||
initial_query_time: Option<Instant>,
|
||||
initial_universe: Option<RoaringBitmap>,
|
||||
ranking_rules_ids: Option<Vec<String>>,
|
||||
events: Vec<SearchEvents>,
|
||||
@ -58,17 +71,19 @@ impl DetailedSearchLogger {
|
||||
pub fn new(folder_path: &str) -> Self {
|
||||
Self {
|
||||
folder_path: PathBuf::new().join(folder_path),
|
||||
initial_query: <_>::default(),
|
||||
initial_universe: <_>::default(),
|
||||
ranking_rules_ids: <_>::default(),
|
||||
events: <_>::default(),
|
||||
initial_query: None,
|
||||
initial_query_time: None,
|
||||
initial_universe: None,
|
||||
ranking_rules_ids: None,
|
||||
events: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
fn initial_query(&mut self, query: &QueryGraph) {
|
||||
fn initial_query(&mut self, query: &QueryGraph, time: Instant) {
|
||||
self.initial_query = Some(query.clone());
|
||||
self.initial_query_time = Some(time);
|
||||
}
|
||||
|
||||
fn initial_universe(&mut self, universe: &RoaringBitmap) {
|
||||
@ -84,11 +99,13 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
_ranking_rule: &dyn RankingRule<'transaction, QueryGraph>,
|
||||
query: &QueryGraph,
|
||||
universe: &RoaringBitmap,
|
||||
time: Instant,
|
||||
) {
|
||||
self.events.push(SearchEvents::RankingRuleStartIteration {
|
||||
ranking_rule_idx,
|
||||
query: query.clone(),
|
||||
universe: universe.clone(),
|
||||
time,
|
||||
})
|
||||
}
|
||||
|
||||
@ -97,10 +114,14 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, QueryGraph>,
|
||||
universe: &RoaringBitmap,
|
||||
candidates: &RoaringBitmap,
|
||||
time: Instant,
|
||||
) {
|
||||
self.events.push(SearchEvents::RankingRuleNextBucket {
|
||||
ranking_rule_idx,
|
||||
universe: universe.clone(),
|
||||
candidates: candidates.clone(),
|
||||
time,
|
||||
})
|
||||
}
|
||||
fn skip_bucket_ranking_rule<'transaction>(
|
||||
@ -108,10 +129,12 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, QueryGraph>,
|
||||
candidates: &RoaringBitmap,
|
||||
time: Instant,
|
||||
) {
|
||||
self.events.push(SearchEvents::RankingRuleSkipBucket {
|
||||
ranking_rule_idx,
|
||||
candidates: candidates.clone(),
|
||||
time
|
||||
})
|
||||
}
|
||||
|
||||
@ -120,10 +143,12 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, QueryGraph>,
|
||||
universe: &RoaringBitmap,
|
||||
time: Instant,
|
||||
) {
|
||||
self.events.push(SearchEvents::RankingRuleEndIteration {
|
||||
ranking_rule_idx,
|
||||
universe: universe.clone(),
|
||||
time
|
||||
})
|
||||
}
|
||||
fn add_to_results(&mut self, docids: &[u32]) {
|
||||
@ -134,18 +159,19 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
||||
self.events.push(SearchEvents::WordsState { query_graph: query_graph.clone() });
|
||||
}
|
||||
|
||||
fn log_proximity_state(&mut self, query_graph: &RankingRuleGraph<ProximityGraph>, paths_map: &PathsMap<u64>, empty_paths_cache: &EmptyPathsCache) {
|
||||
self.events.push(SearchEvents::ProximityState { graph: query_graph.clone(), paths: paths_map.clone(), empty_paths_cache: empty_paths_cache.clone() })
|
||||
fn log_proximity_state(&mut self, query_graph: &RankingRuleGraph<ProximityGraph>, paths_map: &[Vec<u32>], empty_paths_cache: &EmptyPathsCache, universe: &RoaringBitmap, distances: Vec<Vec<u64>>, cost: u64,) {
|
||||
self.events.push(SearchEvents::ProximityState { graph: query_graph.clone(), paths: paths_map.to_vec(), empty_paths_cache: empty_paths_cache.clone(), universe: universe.clone(), distances, cost })
|
||||
}
|
||||
|
||||
fn log_typo_state(&mut self, query_graph: &RankingRuleGraph<TypoGraph>, paths_map: &PathsMap<u64>, empty_paths_cache: &EmptyPathsCache) {
|
||||
self.events.push(SearchEvents::TypoState { graph: query_graph.clone(), paths: paths_map.clone(), empty_paths_cache: empty_paths_cache.clone() })
|
||||
fn log_typo_state(&mut self, query_graph: &RankingRuleGraph<TypoGraph>, paths_map: &[Vec<u32>], empty_paths_cache: &EmptyPathsCache, universe: &RoaringBitmap, distances: Vec<Vec<u64>>, cost: u64,) {
|
||||
self.events.push(SearchEvents::TypoState { graph: query_graph.clone(), paths: paths_map.to_vec(), empty_paths_cache: empty_paths_cache.clone(), universe: universe.clone(), distances, cost })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl DetailedSearchLogger {
|
||||
pub fn write_d2_description(&self) {
|
||||
let mut prev_time = self.initial_query_time.unwrap();
|
||||
let mut timestamp = vec![];
|
||||
fn activated_id(timestamp: &[usize]) -> String {
|
||||
let mut s = String::new();
|
||||
@ -164,13 +190,16 @@ impl DetailedSearchLogger {
|
||||
writeln!(&mut file, "{idx}: {rr_id}").unwrap();
|
||||
}
|
||||
writeln!(&mut file, "results").unwrap();
|
||||
// writeln!(&mut file, "time").unwrap();
|
||||
for event in self.events.iter() {
|
||||
match event {
|
||||
SearchEvents::RankingRuleStartIteration { ranking_rule_idx, .. } => {
|
||||
|
||||
SearchEvents::RankingRuleStartIteration { ranking_rule_idx, time, .. } => {
|
||||
let elapsed = time.duration_since(prev_time);
|
||||
prev_time = *time;
|
||||
let parent_activated_id = activated_id(×tamp);
|
||||
timestamp.push(0);
|
||||
let self_activated_id = activated_id(×tamp);
|
||||
// writeln!(&mut file, "time.{self_activated_id}: {:.2}", elapsed.as_micros() as f64 / 1000.0).unwrap();
|
||||
if *ranking_rule_idx != 0 {
|
||||
let parent_ranking_rule_idx = ranking_rule_idx - 1;
|
||||
writeln!(
|
||||
@ -186,16 +215,22 @@ impl DetailedSearchLogger {
|
||||
}}
|
||||
}}").unwrap();
|
||||
}
|
||||
SearchEvents::RankingRuleNextBucket { ranking_rule_idx, .. } => {
|
||||
SearchEvents::RankingRuleNextBucket { ranking_rule_idx, time, universe, candidates } => {
|
||||
let elapsed = time.duration_since(prev_time);
|
||||
prev_time = *time;
|
||||
let old_activated_id = activated_id(×tamp);
|
||||
// writeln!(&mut file, "time.{old_activated_id}: {:.2}", elapsed.as_micros() as f64 / 1000.0).unwrap();
|
||||
*timestamp.last_mut().unwrap() += 1;
|
||||
let next_activated_id = activated_id(×tamp);
|
||||
writeln!(&mut file,
|
||||
"{ranking_rule_idx}.{old_activated_id} -> {ranking_rule_idx}.{next_activated_id} : next bucket",)
|
||||
"{ranking_rule_idx}.{old_activated_id} -> {ranking_rule_idx}.{next_activated_id} : next bucket {}/{}", candidates.len(), universe.len())
|
||||
.unwrap();
|
||||
}
|
||||
SearchEvents::RankingRuleSkipBucket { ranking_rule_idx, candidates } => {
|
||||
SearchEvents::RankingRuleSkipBucket { ranking_rule_idx, candidates, time } => {
|
||||
let elapsed = time.duration_since(prev_time);
|
||||
prev_time = *time;
|
||||
let old_activated_id = activated_id(×tamp);
|
||||
// writeln!(&mut file, "time.{old_activated_id}: {:.2}", elapsed.as_micros() as f64 / 1000.0).unwrap();
|
||||
*timestamp.last_mut().unwrap() += 1;
|
||||
let next_activated_id = activated_id(×tamp);
|
||||
let len = candidates.len();
|
||||
@ -203,8 +238,12 @@ impl DetailedSearchLogger {
|
||||
"{ranking_rule_idx}.{old_activated_id} -> {ranking_rule_idx}.{next_activated_id} : skip bucket ({len})",)
|
||||
.unwrap();
|
||||
}
|
||||
SearchEvents::RankingRuleEndIteration { ranking_rule_idx, .. } => {
|
||||
SearchEvents::RankingRuleEndIteration { ranking_rule_idx, time, .. } => {
|
||||
let elapsed = time.duration_since(prev_time);
|
||||
prev_time = *time;
|
||||
let cur_activated_id = activated_id(×tamp);
|
||||
// writeln!(&mut file, "time.{cur_activated_id}: {:.2}", elapsed.as_micros() as f64 / 1000.0).unwrap();
|
||||
|
||||
timestamp.pop();
|
||||
let parent_activated_id = activated_id(×tamp);
|
||||
let parent_ranking_rule = if *ranking_rule_idx == 0 {
|
||||
@ -254,43 +293,48 @@ results.{random} {{
|
||||
link: \"{id}.d2.svg\"
|
||||
}}").unwrap();
|
||||
},
|
||||
SearchEvents::ProximityState { graph, paths, empty_paths_cache } => {
|
||||
SearchEvents::ProximityState { graph, paths, empty_paths_cache, universe, distances, cost } => {
|
||||
let cur_ranking_rule = timestamp.len() - 1;
|
||||
let cur_activated_id = activated_id(×tamp);
|
||||
let id = format!("{cur_ranking_rule}.{cur_activated_id}");
|
||||
let new_file_path = self.folder_path.join(format!("{id}.d2"));
|
||||
let mut new_file = std::fs::File::create(new_file_path).unwrap();
|
||||
Self::ranking_rule_graph_d2_description(graph, paths, empty_paths_cache, &mut new_file);
|
||||
Self::ranking_rule_graph_d2_description(graph, paths, empty_paths_cache, distances.clone(), &mut new_file);
|
||||
writeln!(
|
||||
&mut file,
|
||||
"{id} {{
|
||||
link: \"{id}.d2.svg\"
|
||||
}}").unwrap();
|
||||
tooltip: \"cost {cost}, universe len: {}\"
|
||||
}}", universe.len()).unwrap();
|
||||
},
|
||||
SearchEvents::TypoState { graph, paths, empty_paths_cache } => {
|
||||
SearchEvents::TypoState { graph, paths, empty_paths_cache, universe, distances, cost } => {
|
||||
let cur_ranking_rule = timestamp.len() - 1;
|
||||
let cur_activated_id = activated_id(×tamp);
|
||||
let id = format!("{cur_ranking_rule}.{cur_activated_id}");
|
||||
let new_file_path = self.folder_path.join(format!("{id}.d2"));
|
||||
let mut new_file = std::fs::File::create(new_file_path).unwrap();
|
||||
Self::ranking_rule_graph_d2_description(graph, paths, empty_paths_cache, &mut new_file);
|
||||
Self::ranking_rule_graph_d2_description(graph, paths, empty_paths_cache, distances.clone(), &mut new_file);
|
||||
writeln!(
|
||||
&mut file,
|
||||
"{id} {{
|
||||
link: \"{id}.d2.svg\"
|
||||
}}").unwrap();
|
||||
tooltip: \"cost {cost}, universe len: {}\"
|
||||
}}", universe.len()).unwrap();
|
||||
},
|
||||
}
|
||||
}
|
||||
writeln!(&mut file, "}}").unwrap();
|
||||
}
|
||||
|
||||
fn query_node_d2_desc(node_idx: usize, node: &QueryNode, file: &mut File) {
|
||||
fn query_node_d2_desc(node_idx: usize, node: &QueryNode, distances: &[u64], file: &mut File) {
|
||||
match &node {
|
||||
QueryNode::Term(LocatedQueryTerm { value, .. }) => {
|
||||
match value {
|
||||
QueryTerm::Phrase(_) => todo!(),
|
||||
QueryTerm::Word { derivations: WordDerivations { original, zero_typo, one_typo, two_typos, use_prefix_db } } => {
|
||||
QueryTerm::Phrase { phrase } => {
|
||||
let phrase_str = phrase.description();
|
||||
writeln!(file,"{node_idx} : \"{phrase_str}\"").unwrap();
|
||||
},
|
||||
QueryTerm::Word { derivations: WordDerivations { original, zero_typo, one_typo, two_typos, use_prefix_db, synonyms, split_words } } => {
|
||||
writeln!(file,"{node_idx} : \"{original}\" {{
|
||||
shape: class").unwrap();
|
||||
for w in zero_typo {
|
||||
@ -302,9 +346,19 @@ shape: class").unwrap();
|
||||
for w in two_typos {
|
||||
writeln!(file, "\"{w}\" : 2").unwrap();
|
||||
}
|
||||
if let Some((left, right)) = split_words {
|
||||
writeln!(file, "\"{left} {right}\" : split_words").unwrap();
|
||||
}
|
||||
for synonym in synonyms {
|
||||
writeln!(file, "\"{}\" : synonym", synonym.description()).unwrap();
|
||||
}
|
||||
if *use_prefix_db {
|
||||
writeln!(file, "use prefix DB : true").unwrap();
|
||||
}
|
||||
// for (i, d) in distances.iter().enumerate() {
|
||||
// writeln!(file, "\"distances\" : {d}").unwrap();
|
||||
// }
|
||||
|
||||
writeln!(file, "}}").unwrap();
|
||||
},
|
||||
}
|
||||
@ -324,14 +378,14 @@ shape: class").unwrap();
|
||||
if matches!(query_graph.nodes[node], QueryNode::Deleted) {
|
||||
continue;
|
||||
}
|
||||
Self::query_node_d2_desc(node, &query_graph.nodes[node], file);
|
||||
Self::query_node_d2_desc(node, &query_graph.nodes[node], &[], file);
|
||||
|
||||
for edge in query_graph.edges[node].successors.iter() {
|
||||
writeln!(file, "{node} -> {edge};\n").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
fn ranking_rule_graph_d2_description<R: RankingRuleGraphTrait>(graph: &RankingRuleGraph<R>, paths: &PathsMap<u64>, empty_paths_cache: &EmptyPathsCache, file: &mut File) {
|
||||
fn ranking_rule_graph_d2_description<R: RankingRuleGraphTrait>(graph: &RankingRuleGraph<R>, paths: &[Vec<u32>], _empty_paths_cache: &EmptyPathsCache, distances: Vec<Vec<u64>>, file: &mut File) {
|
||||
writeln!(file,"direction: right").unwrap();
|
||||
|
||||
writeln!(file, "Proximity Graph {{").unwrap();
|
||||
@ -339,7 +393,8 @@ shape: class").unwrap();
|
||||
if matches!(node, QueryNode::Deleted) {
|
||||
continue;
|
||||
}
|
||||
Self::query_node_d2_desc(node_idx, node, file);
|
||||
let distances = &distances[node_idx];
|
||||
Self::query_node_d2_desc(node_idx, node, distances.as_slice(), file);
|
||||
}
|
||||
for edge in graph.all_edges.iter().flatten() {
|
||||
let Edge { from_node, to_node, details, .. } = edge;
|
||||
@ -362,26 +417,39 @@ shape: class").unwrap();
|
||||
}
|
||||
writeln!(file, "}}").unwrap();
|
||||
|
||||
// writeln!(file, "Distances {{").unwrap();
|
||||
// Self::paths_d2_description(graph, paths, file);
|
||||
// writeln!(file, "}}").unwrap();
|
||||
|
||||
|
||||
writeln!(file, "Shortest Paths {{").unwrap();
|
||||
Self::paths_d2_description(graph, "", paths, file);
|
||||
Self::paths_d2_description(graph, paths, file);
|
||||
writeln!(file, "}}").unwrap();
|
||||
|
||||
writeln!(file, "Empty Path Prefixes {{").unwrap();
|
||||
Self::paths_d2_description(graph, "", &empty_paths_cache.empty_prefixes, file);
|
||||
writeln!(file, "}}").unwrap();
|
||||
// writeln!(file, "Empty Edge Couples {{").unwrap();
|
||||
// for (i, (e1, e2)) in empty_paths_cache.empty_couple_edges.iter().enumerate() {
|
||||
// writeln!(file, "{i} : \"\" {{").unwrap();
|
||||
// Self::edge_d2_description(graph, *e1, file);
|
||||
// Self::edge_d2_description(graph, *e2, file);
|
||||
// writeln!(file, "{e1} -- {e2}").unwrap();
|
||||
// writeln!(file, "}}").unwrap();
|
||||
// }
|
||||
// writeln!(file, "}}").unwrap();
|
||||
|
||||
writeln!(file, "Removed Edges {{").unwrap();
|
||||
for edge_idx in empty_paths_cache.empty_edges.iter() {
|
||||
writeln!(file, "{edge_idx}").unwrap();
|
||||
}
|
||||
writeln!(file, "}}").unwrap();
|
||||
// writeln!(file, "Removed Edges {{").unwrap();
|
||||
// for edge_idx in empty_paths_cache.empty_edges.iter() {
|
||||
// writeln!(file, "{edge_idx}").unwrap();
|
||||
// }
|
||||
// writeln!(file, "}}").unwrap();
|
||||
}
|
||||
fn edge_d2_description<R: RankingRuleGraphTrait>(graph: &RankingRuleGraph<R>, paths_idx: &str, edge_idx: u32, file: &mut File) -> String {
|
||||
fn edge_d2_description<R: RankingRuleGraphTrait>(graph: &RankingRuleGraph<R>, edge_idx: u32, file: &mut File) {
|
||||
let Edge { from_node, to_node, cost, .. } = graph.all_edges[edge_idx as usize].as_ref().unwrap() ;
|
||||
let from_node = &graph.query_graph.nodes[*from_node as usize];
|
||||
let from_node_desc = match from_node {
|
||||
QueryNode::Term(term) => match &term.value {
|
||||
QueryTerm::Phrase(_) => todo!(),
|
||||
QueryTerm::Phrase { phrase } => {
|
||||
phrase.description()
|
||||
},
|
||||
QueryTerm::Word { derivations } => derivations.original.clone(),
|
||||
},
|
||||
QueryNode::Deleted => panic!(),
|
||||
@ -391,27 +459,28 @@ shape: class").unwrap();
|
||||
let to_node = &graph.query_graph.nodes[*to_node as usize];
|
||||
let to_node_desc = match to_node {
|
||||
QueryNode::Term(term) => match &term.value {
|
||||
QueryTerm::Phrase(_) => todo!(),
|
||||
QueryTerm::Phrase { phrase } => phrase.description(),
|
||||
QueryTerm::Word { derivations } => derivations.original.clone(),
|
||||
},
|
||||
QueryNode::Deleted => panic!(),
|
||||
QueryNode::Start => "START".to_owned(),
|
||||
QueryNode::End => "END".to_owned(),
|
||||
};
|
||||
let edge_id = format!("{paths_idx}{edge_idx}");
|
||||
writeln!(file, "{edge_id}: \"{from_node_desc}->{to_node_desc} [{cost}]\" {{
|
||||
writeln!(file, "{edge_idx}: \"{from_node_desc}->{to_node_desc} [{cost}]\" {{
|
||||
shape: class
|
||||
}}").unwrap();
|
||||
edge_id
|
||||
}
|
||||
fn paths_d2_description<R: RankingRuleGraphTrait, T>(graph: &RankingRuleGraph<R>, paths_idx: &str, paths: &PathsMap<T>, file: &mut File) {
|
||||
for (edge_idx, rest) in paths.nodes.iter() {
|
||||
let edge_id = Self::edge_d2_description(graph, paths_idx, *edge_idx, file);
|
||||
for (dest_edge_idx, _) in rest.nodes.iter() {
|
||||
let dest_edge_id = format!("{paths_idx}{edge_idx}{dest_edge_idx}");
|
||||
writeln!(file, "{edge_id} -> {dest_edge_id}").unwrap();
|
||||
fn paths_d2_description<R: RankingRuleGraphTrait>(graph: &RankingRuleGraph<R>, paths: &[Vec<u32>], file: &mut File) {
|
||||
for (path_idx, edge_indexes) in paths.iter().enumerate() {
|
||||
writeln!(file, "{path_idx} {{").unwrap();
|
||||
for edge_idx in edge_indexes.iter() {
|
||||
Self::edge_d2_description(graph, *edge_idx, file);
|
||||
}
|
||||
Self::paths_d2_description(graph, &format!("{paths_idx}{edge_idx}"), rest, file);
|
||||
for couple_edges in edge_indexes.windows(2) {
|
||||
let [src_edge_idx, dest_edge_idx] = couple_edges else { panic!() };
|
||||
writeln!(file, "{src_edge_idx} -> {dest_edge_idx}").unwrap();
|
||||
}
|
||||
writeln!(file, "}}").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,28 +2,31 @@
|
||||
pub mod detailed;
|
||||
|
||||
use roaring::RoaringBitmap;
|
||||
use std::time::Instant;
|
||||
|
||||
use super::{
|
||||
ranking_rule_graph::{
|
||||
empty_paths_cache::EmptyPathsCache, paths_map::PathsMap, proximity::ProximityGraph,
|
||||
typo::TypoGraph, RankingRuleGraph,
|
||||
empty_paths_cache::EmptyPathsCache, proximity::ProximityGraph, typo::TypoGraph,
|
||||
RankingRuleGraph,
|
||||
},
|
||||
RankingRule, RankingRuleQueryTrait,
|
||||
};
|
||||
|
||||
pub struct DefaultSearchLogger;
|
||||
impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
||||
fn initial_query(&mut self, _query: &Q) {}
|
||||
fn initial_query(&mut self, _query: &Q, _time: Instant) {}
|
||||
|
||||
fn initial_universe(&mut self, _universe: &RoaringBitmap) {}
|
||||
|
||||
fn ranking_rules(&mut self, _rr: &[&mut dyn RankingRule<Q>]) {}
|
||||
|
||||
fn start_iteration_ranking_rule<'transaction>(
|
||||
&mut self,
|
||||
_ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
_query: &Q,
|
||||
_universe: &RoaringBitmap,
|
||||
_time: Instant,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -32,6 +35,8 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
||||
_ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
_universe: &RoaringBitmap,
|
||||
_candidates: &RoaringBitmap,
|
||||
_time: Instant,
|
||||
) {
|
||||
}
|
||||
fn skip_bucket_ranking_rule<'transaction>(
|
||||
@ -39,6 +44,7 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
||||
_ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
_candidates: &RoaringBitmap,
|
||||
_time: Instant,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -47,6 +53,7 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
||||
_ranking_rule_idx: usize,
|
||||
_ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
_universe: &RoaringBitmap,
|
||||
_time: Instant,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -57,22 +64,28 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
||||
fn log_proximity_state(
|
||||
&mut self,
|
||||
_query_graph: &RankingRuleGraph<ProximityGraph>,
|
||||
_paths_map: &PathsMap<u64>,
|
||||
_paths_map: &[Vec<u32>],
|
||||
_empty_paths_cache: &EmptyPathsCache,
|
||||
_universe: &RoaringBitmap,
|
||||
_distances: Vec<Vec<u64>>,
|
||||
_cost: u64,
|
||||
) {
|
||||
}
|
||||
|
||||
fn log_typo_state(
|
||||
&mut self,
|
||||
query_graph: &RankingRuleGraph<TypoGraph>,
|
||||
paths: &PathsMap<u64>,
|
||||
empty_paths_cache: &EmptyPathsCache,
|
||||
_query_graph: &RankingRuleGraph<TypoGraph>,
|
||||
_paths: &[Vec<u32>],
|
||||
_empty_paths_cache: &EmptyPathsCache,
|
||||
_universe: &RoaringBitmap,
|
||||
_distances: Vec<Vec<u64>>,
|
||||
_cost: u64,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SearchLogger<Q: RankingRuleQueryTrait> {
|
||||
fn initial_query(&mut self, query: &Q);
|
||||
fn initial_query(&mut self, query: &Q, time: Instant);
|
||||
fn initial_universe(&mut self, universe: &RoaringBitmap);
|
||||
|
||||
fn ranking_rules(&mut self, rr: &[&mut dyn RankingRule<Q>]);
|
||||
@ -83,24 +96,29 @@ pub trait SearchLogger<Q: RankingRuleQueryTrait> {
|
||||
ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
query: &Q,
|
||||
universe: &RoaringBitmap,
|
||||
time: Instant,
|
||||
);
|
||||
fn next_bucket_ranking_rule<'transaction>(
|
||||
&mut self,
|
||||
ranking_rule_idx: usize,
|
||||
ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
universe: &RoaringBitmap,
|
||||
candidates: &RoaringBitmap,
|
||||
time: Instant,
|
||||
);
|
||||
fn skip_bucket_ranking_rule<'transaction>(
|
||||
&mut self,
|
||||
ranking_rule_idx: usize,
|
||||
ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
candidates: &RoaringBitmap,
|
||||
time: Instant,
|
||||
);
|
||||
fn end_iteration_ranking_rule<'transaction>(
|
||||
&mut self,
|
||||
ranking_rule_idx: usize,
|
||||
ranking_rule: &dyn RankingRule<'transaction, Q>,
|
||||
universe: &RoaringBitmap,
|
||||
time: Instant,
|
||||
);
|
||||
fn add_to_results(&mut self, docids: &[u32]);
|
||||
|
||||
@ -109,14 +127,20 @@ pub trait SearchLogger<Q: RankingRuleQueryTrait> {
|
||||
fn log_proximity_state(
|
||||
&mut self,
|
||||
query_graph: &RankingRuleGraph<ProximityGraph>,
|
||||
paths: &PathsMap<u64>,
|
||||
paths: &[Vec<u32>],
|
||||
empty_paths_cache: &EmptyPathsCache,
|
||||
universe: &RoaringBitmap,
|
||||
_distances: Vec<Vec<u64>>,
|
||||
cost: u64,
|
||||
);
|
||||
|
||||
fn log_typo_state(
|
||||
&mut self,
|
||||
query_graph: &RankingRuleGraph<TypoGraph>,
|
||||
paths: &PathsMap<u64>,
|
||||
paths: &[Vec<u32>],
|
||||
empty_paths_cache: &EmptyPathsCache,
|
||||
universe: &RoaringBitmap,
|
||||
_distances: Vec<Vec<u64>>,
|
||||
cost: u64,
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user