elefant_client/
profiler.rs1use std::collections::HashMap;
2use std::sync::{Mutex, OnceLock};
3use std::time::Duration;
4
5pub struct Profiler {
6 measurements: Mutex<HashMap<&'static str, Measurement>>,
7}
8
9#[derive(Debug)]
10pub struct Measurement {
11 duration: Duration,
12 count: u64,
13}
14
15static PROFILER: OnceLock<Profiler> = OnceLock::new();
16
17impl Profiler {
18 fn get() -> &'static Profiler {
19 PROFILER.get_or_init(|| Profiler {
20 measurements: Mutex::new(HashMap::new()),
21 })
22 }
23
24 pub fn start(name: &'static str) -> ProfilerGuard {
25 ProfilerGuard {
26 name,
27 start: std::time::Instant::now(),
28 }
29 }
30
31 pub fn print_results() {
32 let measurements = Profiler::get().measurements.lock().unwrap();
33
34 let mut items = measurements.iter().collect::<Vec<_>>();
35 items.sort_by(|a, b| a.1.duration.cmp(&b.1.duration).reverse());
36
37 for (name, duration) in items {
38 println!("{name}: {duration:?}");
39 }
40 }
41
42 pub fn reset() {
43 let mut measurements = Profiler::get().measurements.lock().unwrap();
44 measurements.clear();
45 }
46}
47
48pub struct ProfilerGuard {
49 name: &'static str,
50 start: std::time::Instant,
51}
52
53impl Drop for ProfilerGuard {
54 fn drop(&mut self) {
55 let elapsed = self.start.elapsed();
56 let mut measurements = Profiler::get().measurements.lock().unwrap();
57 let entry = measurements.entry(self.name);
58 match entry {
59 std::collections::hash_map::Entry::Occupied(mut entry) => {
60 let current = entry.get_mut();
61 current.duration += elapsed;
62 current.count += 1;
63 }
64 std::collections::hash_map::Entry::Vacant(entry) => {
65 entry.insert(Measurement {
66 duration: elapsed,
67 count: 1,
68 });
69 }
70 }
71 }
72}