ryna/algorithms/
profiling.rs

1use std::{sync::Mutex, time::Instant};
2
3use rustc_hash::FxHashMap;
4use tabled::{settings::Style, Table, Tabled};
5
6lazy_static! {
7    pub static ref PROFILER: Mutex<FxHashMap<&'static str, (u128, usize)>> = Mutex::default();
8}
9
10pub struct ProfSpan {
11    name: &'static str,
12    start: Instant
13}
14
15impl ProfSpan {
16    pub fn new(name: &'static str) -> Self {
17        ProfSpan { start: Instant::now(), name }
18    }
19
20    pub fn end(&self) {
21        let elapsed = self.start.elapsed().as_nanos();
22
23        let mut p_entry = PROFILER.lock().unwrap();
24        let entry_data = p_entry.entry(self.name).or_insert((0, 0));
25
26        entry_data.0 += elapsed;
27        entry_data.1 += 1;
28    }
29}
30
31#[macro_export]
32macro_rules! profile {
33    ($name: expr, $expr: expr) => {
34        {
35            let span = $crate::profiling::ProfSpan::new($name);
36
37            let res = $expr;
38    
39            span.end();
40    
41            res    
42        }
43    };
44}
45
46#[derive(Tabled)]
47struct ProfilerEntry {
48    name: &'static str,
49    total_time: u128,
50    time: u128,
51    count: usize,
52    percentage: f32
53}
54
55pub fn clear_profiler() {
56    PROFILER.lock().unwrap().clear();
57}
58
59pub fn print_profiler_results() {
60    let mut entries = PROFILER.lock().unwrap().iter().map(|(a, b)| (*a, *b)).collect::<Vec<_>>();
61    entries.sort_by_key(|(_, i)| *i);
62    entries.reverse();
63
64    let total_time = entries.iter().map(|(_, (i, _))| *i).sum::<u128>();
65
66    let table = Table::new(
67        entries.into_iter().map(|(name, (time, count))| ProfilerEntry {
68            name,
69            total_time: time / 1000000,
70            count,
71            time: time / count as u128,
72            percentage: (time as f64 / total_time as f64) as f32,
73        })
74    ).with(Style::modern_rounded()).to_string();
75
76    print!("{}", table);
77}