use crate::*;
static PERF_COUNTERS: Lazy<AtomicRefCell<PerfCounters>> =
Lazy::new(|| AtomicRefCell::new(PerfCounters::default()));
static TIMINGS: Lazy<AtomicRefCell<Timings>> =
Lazy::new(|| AtomicRefCell::new(Timings::new()));
pub struct TimingEntry {
pub history: egui::util::History<Duration>,
pub time: Instant,
}
pub struct Timings {
pub data: HashMap<&'static str, TimingEntry>,
}
impl Timings {
pub fn new() -> Self {
Self { data: HashMap::new() }
}
pub fn add_value(
&mut self,
name: &'static str,
value: Duration,
time: Instant,
) {
let entry = self.data.entry(name).or_insert(TimingEntry {
history: egui::util::History::new(50..2000, 2.0),
time: Instant::now(),
});
entry.time = time;
entry.history.add(get_time(), value);
}
pub fn span(&mut self, name: &'static str) -> TimingGuard<'_> {
TimingGuard { timings: self, name, start: Instant::now() }
}
}
pub struct TimingGuard<'a> {
timings: &'a mut Timings,
name: &'static str,
start: Instant,
}
impl<'a> Drop for TimingGuard<'a> {
fn drop(&mut self) {
self.timings.add_value(self.name, self.start.elapsed(), self.start);
}
}
pub struct AtomicTimingGuard {
name: &'static str,
start: Instant,
}
impl Drop for AtomicTimingGuard {
fn drop(&mut self) {
TIMINGS.borrow_mut().add_value(
self.name,
self.start.elapsed(),
self.start,
);
}
}
pub fn timings() -> impl std::ops::Deref<Target = Timings> {
TIMINGS.borrow_mut()
}
pub fn timing_start(name: &'static str) -> AtomicTimingGuard {
AtomicTimingGuard { name, start: Instant::now() }
}
pub fn timings_add_value(name: &'static str, value: f32) {
TIMINGS.borrow_mut().add_value(
name,
Duration::from_secs_f32(value),
Instant::now(),
);
}
#[derive(Default)]
pub struct PerfCounters {
pub counters: HashMap<Cow<'static, str>, Counter>,
}
#[derive(Default)]
pub struct Counter {
pub count: u64,
pub decayed_average: f64,
}
impl PerfCounters {
pub fn global() -> AtomicRef<'static, PerfCounters> {
PERF_COUNTERS.borrow()
}
pub fn update_counter(
&mut self,
counter_name: impl Into<Cow<'static, str>>,
count: u64,
) {
let counter = self.counters.entry(counter_name.into()).or_default();
counter.count = count;
}
pub fn new_frame(&mut self, delta: f64) {
for counter in self.counters.values_mut() {
let t = delta * 5.0;
counter.decayed_average = counter.decayed_average * (1.0 - t) +
(counter.count as f64) * t;
counter.count = 0;
}
}
pub fn get_counter(&self, counter_name: &str) -> (u64, f64) {
if let Some(counter) = self.counters.get(counter_name) {
(counter.count, counter.decayed_average)
} else {
(0, 0.0)
}
}
pub fn reset_counters(&mut self) {
self.counters.clear();
}
}
pub fn perf_counters_new_frame(delta: f64) {
let mut counters = PERF_COUNTERS.borrow_mut();
counters.new_frame(delta);
}
pub fn reset_perf_counters() {
let mut counters = PERF_COUNTERS.borrow_mut();
counters.reset_counters();
}
pub fn perf_counter(counter_name: impl Into<Cow<'static, str>>, count: u64) {
let mut counters = PERF_COUNTERS.borrow_mut();
counters.update_counter(counter_name, count);
}
pub fn perf_counter_inc(counter_name: impl Into<Cow<'static, str>>, inc: u64) {
let mut counters = PERF_COUNTERS.borrow_mut();
let counter_name_cow = counter_name.into();
let (current_value, _) = counters.get_counter(&counter_name_cow);
counters.update_counter(counter_name_cow, current_value + inc);
}
pub fn get_perf_counter(
counter_name: impl Into<Cow<'static, str>>,
) -> (u64, f64) {
let counters = PERF_COUNTERS.borrow_mut();
counters.get_counter(&counter_name.into())
}