ryna/algorithms/
profiling.rs1use 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}