comfy_core/
perf_counters.rs

1use crate::*;
2
3static PERF_COUNTERS: Lazy<AtomicRefCell<PerfCounters>> =
4    Lazy::new(|| AtomicRefCell::new(PerfCounters::default()));
5
6static TIMINGS: Lazy<AtomicRefCell<Timings>> =
7    Lazy::new(|| AtomicRefCell::new(Timings::new()));
8
9pub struct TimingEntry {
10    pub history: egui::util::History<Duration>,
11    pub time: Instant,
12}
13
14pub struct Timings {
15    pub data: HashMap<&'static str, TimingEntry>,
16}
17
18impl Timings {
19    pub fn new() -> Self {
20        Self { data: HashMap::new() }
21    }
22
23    pub fn add_value(
24        &mut self,
25        name: &'static str,
26        value: Duration,
27        time: Instant,
28    ) {
29        let entry = self.data.entry(name).or_insert(TimingEntry {
30            history: egui::util::History::new(50..2000, 2.0),
31            time: Instant::now(),
32        });
33
34        entry.time = time;
35        entry.history.add(get_time(), value);
36    }
37
38    pub fn span(&mut self, name: &'static str) -> TimingGuard<'_> {
39        TimingGuard { timings: self, name, start: Instant::now() }
40    }
41}
42
43pub struct TimingGuard<'a> {
44    timings: &'a mut Timings,
45    name: &'static str,
46    start: Instant,
47}
48
49impl<'a> Drop for TimingGuard<'a> {
50    fn drop(&mut self) {
51        self.timings.add_value(self.name, self.start.elapsed(), self.start);
52    }
53}
54
55pub struct AtomicTimingGuard {
56    name: &'static str,
57    start: Instant,
58}
59
60impl Drop for AtomicTimingGuard {
61    fn drop(&mut self) {
62        TIMINGS.borrow_mut().add_value(
63            self.name,
64            self.start.elapsed(),
65            self.start,
66        );
67    }
68}
69
70pub fn timings() -> impl std::ops::Deref<Target = Timings> {
71    TIMINGS.borrow_mut()
72}
73
74pub fn timing_start(name: &'static str) -> AtomicTimingGuard {
75    AtomicTimingGuard { name, start: Instant::now() }
76}
77
78/// Add a timing value to a given timer, measured in f32 seconds.
79pub fn timings_add_value(name: &'static str, value: f32) {
80    TIMINGS.borrow_mut().add_value(
81        name,
82        Duration::from_secs_f32(value),
83        Instant::now(),
84    );
85}
86
87#[derive(Default)]
88pub struct PerfCounters {
89    // pub counters: HashMap<String, Counter>,
90    pub counters: HashMap<Cow<'static, str>, Counter>,
91}
92
93#[derive(Default)]
94pub struct Counter {
95    pub count: u64,
96    pub decayed_average: f64,
97}
98
99impl PerfCounters {
100    pub fn global() -> AtomicRef<'static, PerfCounters> {
101        PERF_COUNTERS.borrow()
102    }
103
104    pub fn update_counter(
105        &mut self,
106        counter_name: impl Into<Cow<'static, str>>,
107        count: u64,
108    ) {
109        let counter = self.counters.entry(counter_name.into()).or_default();
110        counter.count = count;
111    }
112
113    pub fn new_frame(&mut self, delta: f64) {
114        for counter in self.counters.values_mut() {
115            let t = delta * 5.0;
116
117            counter.decayed_average = counter.decayed_average * (1.0 - t) +
118                (counter.count as f64) * t;
119
120            counter.count = 0;
121        }
122    }
123
124    pub fn get_counter(&self, counter_name: &str) -> (u64, f64) {
125        if let Some(counter) = self.counters.get(counter_name) {
126            (counter.count, counter.decayed_average)
127        } else {
128            (0, 0.0)
129        }
130    }
131
132    pub fn reset_counters(&mut self) {
133        self.counters.clear();
134    }
135}
136
137pub fn perf_counters_new_frame(delta: f64) {
138    let mut counters = PERF_COUNTERS.borrow_mut();
139    counters.new_frame(delta);
140}
141
142pub fn reset_perf_counters() {
143    let mut counters = PERF_COUNTERS.borrow_mut();
144    counters.reset_counters();
145}
146
147pub fn perf_counter(counter_name: impl Into<Cow<'static, str>>, count: u64) {
148    let mut counters = PERF_COUNTERS.borrow_mut();
149    counters.update_counter(counter_name, count);
150}
151
152pub fn perf_counter_inc(counter_name: impl Into<Cow<'static, str>>, inc: u64) {
153    let mut counters = PERF_COUNTERS.borrow_mut();
154    let counter_name_cow = counter_name.into();
155    let (current_value, _) = counters.get_counter(&counter_name_cow);
156    counters.update_counter(counter_name_cow, current_value + inc);
157}
158
159pub fn get_perf_counter(
160    counter_name: impl Into<Cow<'static, str>>,
161) -> (u64, f64) {
162    let counters = PERF_COUNTERS.borrow_mut();
163    counters.get_counter(&counter_name.into())
164}
165
166// pub fn perf_counter(counter_name: &str, count: u64) {
167//     let mut counters = PERF_COUNTERS.borrow_mut();
168//     counters.update_counter(counter_name, count);
169// }
170//
171// pub fn perf_counter_inc(counter_name: &str) {
172//     let mut counters = PERF_COUNTERS.borrow_mut();
173//     let (current_value, _) = counters.get_counter(counter_name);
174//     counters.update_counter(counter_name, current_value + 1);
175// }
176//
177// pub fn get_perf_counter(counter_name: &str) -> (u64, f64) {
178//     let counters = PERF_COUNTERS.borrow_mut();
179//     counters.get_counter(counter_name)
180// }