evobench_tools/evaluator/
index_by_call_path.rs1use std::{
5 collections::{HashMap, hash_map},
6 time::SystemTime,
7};
8
9use chj_rustbin::chunks::ChunksOp;
10use rayon::iter::{ParallelBridge, ParallelIterator};
11
12use crate::evaluator::data::log_data_tree::{LogDataTree, PathStringOptions, SpanId};
13
14#[derive(Debug, Default)]
15pub struct IndexByCallPath<'t> {
16 spans_by_call_path: HashMap<String, Vec<SpanId<'t>>>,
19}
20
21impl<'t> IndexByCallPath<'t> {
22 pub fn from_logdataindex(
23 log_data_tree: &LogDataTree<'t>,
24 path_string_optss: &[PathStringOptions],
25 ) -> Self {
26 let t0 = SystemTime::now();
27
28 let make_locals = || -> (String, String, HashMap<String, Vec<SpanId<'t>>>) {
29 (Default::default(), Default::default(), Default::default())
30 };
31 let spans_by_call_path = ChunksOp::chunks(log_data_tree.span_ids(), 1000)
32 .par_bridge()
33 .map(|span_ids| {
34 let (mut out_prefix, mut out_main, mut spans_by_call_path) = make_locals();
35 for span_id in span_ids {
36 let span = span_id.get_from_db(log_data_tree);
37 for opts in path_string_optss {
38 let path = {
39 out_prefix.clear();
42 out_main.clear();
43 span.path_string(&opts, log_data_tree, &mut out_prefix, &mut out_main);
44 out_prefix.push_str(&out_main);
45 &*out_prefix
46 };
47 match spans_by_call_path.get_mut(path) {
49 Some(vec) => {
50 vec.push(span_id);
51 }
52 None => {
53 spans_by_call_path.insert(path.to_owned(), vec![span_id]);
54 }
55 }
56 }
57 }
58 spans_by_call_path
59 })
60 .reduce(
61 || HashMap::new(),
62 |mut spans_by_call_path, hm| {
63 for (k, mut v) in hm {
64 match spans_by_call_path.entry(k) {
65 hash_map::Entry::Occupied(occupied_entry) => {
66 occupied_entry.into_mut().append(&mut v);
67 }
68 hash_map::Entry::Vacant(vacant_entry) => {
69 vacant_entry.insert(v);
70 }
71 }
72 }
73 spans_by_call_path
74 },
75 );
76
77 let t1 = SystemTime::now();
78 eprintln!(
79 "t IndexByCallPath::from_logdataindex: {} s",
80 t1.duration_since(t0).unwrap().as_secs_f64()
81 );
82
83 Self { spans_by_call_path }
84 }
85
86 pub fn call_paths(&self) -> Vec<&String> {
87 let mut paths: Vec<&String> = self.spans_by_call_path.keys().collect();
88 paths.sort();
89 paths
90 }
91
92 pub fn spans_by_call_path(&self, call_path: &str) -> Option<&Vec<SpanId<'_>>> {
93 self.spans_by_call_path.get(call_path)
94 }
95}