#[cfg(any(test, debug_assertions))]
mod active {
use std::{
cell::{Cell, RefCell},
env,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) struct TuiPerfSnapshot {
pub(crate) frame: u64,
pub(crate) last_drain_us: u64,
pub(crate) max_drain_us: u64,
pub(crate) last_draw_us: u64,
pub(crate) max_draw_us: u64,
pub(crate) projected_cards: usize,
pub(crate) backlog_before_drain: usize,
pub(crate) backlog_after_drain: usize,
pub(crate) backlog_before_draw: usize,
}
#[derive(Debug, Default)]
pub(crate) struct TuiPerfCounters {
enabled: Cell<bool>,
frame: Cell<u64>,
last_drain_us: Cell<u64>,
max_drain_us: Cell<u64>,
last_draw_us: Cell<u64>,
max_draw_us: Cell<u64>,
projected_cards: Cell<usize>,
backlog_before_drain: Cell<usize>,
backlog_after_drain: Cell<usize>,
backlog_before_draw: Cell<usize>,
latest_snapshot: RefCell<Option<TuiPerfSnapshot>>,
}
impl TuiPerfCounters {
pub(crate) fn from_env() -> Self {
Self::with_enabled(env_enabled())
}
pub(crate) fn with_enabled(enabled: bool) -> Self {
Self {
enabled: Cell::new(enabled),
..Default::default()
}
}
pub(crate) fn enabled(&self) -> bool {
self.enabled.get()
}
pub(crate) fn set_backlog_before_drain(&self, backlog: usize) {
if self.enabled() {
self.backlog_before_drain.set(backlog);
}
}
pub(crate) fn set_backlog_after_drain(&self, backlog: usize) {
if self.enabled() {
self.backlog_after_drain.set(backlog);
}
}
pub(crate) fn set_backlog_before_draw(&self, backlog: usize) {
if self.enabled() {
self.backlog_before_draw.set(backlog);
}
}
pub(crate) fn record_drain_us(&self, elapsed_us: u64) {
if !self.enabled() {
return;
}
self.last_drain_us.set(elapsed_us);
self.max_drain_us
.set(self.max_drain_us.get().max(elapsed_us));
}
pub(crate) fn reset_projected_cards(&self) {
if self.enabled() {
self.projected_cards.set(0);
}
}
pub(crate) fn increment_projected_cards(&self) {
if self.enabled() {
self.projected_cards
.set(self.projected_cards.get().saturating_add(1));
}
}
pub(crate) fn record_draw_us(&self, elapsed_us: u64) {
if !self.enabled() {
return;
}
self.last_draw_us.set(elapsed_us);
self.max_draw_us.set(self.max_draw_us.get().max(elapsed_us));
self.frame.set(self.frame.get().saturating_add(1));
let snapshot = TuiPerfSnapshot {
frame: self.frame.get(),
last_drain_us: self.last_drain_us.get(),
max_drain_us: self.max_drain_us.get(),
last_draw_us: self.last_draw_us.get(),
max_draw_us: self.max_draw_us.get(),
projected_cards: self.projected_cards.get(),
backlog_before_drain: self.backlog_before_drain.get(),
backlog_after_drain: self.backlog_after_drain.get(),
backlog_before_draw: self.backlog_before_draw.get(),
};
*self.latest_snapshot.borrow_mut() = Some(snapshot);
}
pub(crate) fn latest_snapshot(&self) -> Option<TuiPerfSnapshot> {
*self.latest_snapshot.borrow()
}
pub(crate) fn footer_text(&self) -> Option<String> {
let snapshot = self.latest_snapshot()?;
Some(format!(
"perf drain {:.1}/{:.1}ms draw {:.1}/{:.1}ms cards {} backlog {}/{}/{}",
micros_to_millis(snapshot.last_drain_us),
micros_to_millis(snapshot.max_drain_us),
micros_to_millis(snapshot.last_draw_us),
micros_to_millis(snapshot.max_draw_us),
snapshot.projected_cards,
snapshot.backlog_before_drain,
snapshot.backlog_after_drain,
snapshot.backlog_before_draw,
))
}
}
fn micros_to_millis(value: u64) -> f64 {
value as f64 / 1000.0
}
fn env_enabled() -> bool {
env_flag_enabled("MAGI_TUI_PERF") || env_flag_enabled("MC_TUI_PERF")
}
fn env_flag_enabled(name: &str) -> bool {
env::var_os(name).is_some_and(|value| value == "1")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tui_perf_disabled_does_not_update_counters() {
let perf = TuiPerfCounters::default();
perf.set_backlog_before_drain(9);
perf.record_drain_us(100);
perf.reset_projected_cards();
perf.increment_projected_cards();
perf.set_backlog_after_drain(3);
perf.set_backlog_before_draw(2);
perf.record_draw_us(200);
assert_eq!(perf.latest_snapshot(), None);
assert_eq!(perf.footer_text(), None);
}
#[test]
fn tui_perf_enabled_records_drain_draw_cards_and_backlog() {
let perf = TuiPerfCounters::with_enabled(true);
perf.set_backlog_before_drain(5);
perf.record_drain_us(400);
perf.increment_projected_cards();
perf.increment_projected_cards();
perf.set_backlog_after_drain(2);
perf.set_backlog_before_draw(1);
perf.record_draw_us(2100);
let snapshot = perf.latest_snapshot().unwrap();
assert_eq!(snapshot.frame, 1);
assert_eq!(snapshot.last_drain_us, 400);
assert_eq!(snapshot.max_drain_us, 400);
assert_eq!(snapshot.last_draw_us, 2100);
assert_eq!(snapshot.max_draw_us, 2100);
assert_eq!(snapshot.projected_cards, 2);
assert_eq!(snapshot.backlog_before_drain, 5);
assert_eq!(snapshot.backlog_after_drain, 2);
assert_eq!(snapshot.backlog_before_draw, 1);
assert!(
perf.footer_text()
.unwrap()
.contains("perf drain 0.4/0.4ms draw 2.1/2.1ms cards 2 backlog 5/2/1")
);
}
#[test]
fn tui_perf_env_reads_supported_flags() {
let env = crate::test_support::env::env_lock();
env.remove_var("MAGI_TUI_PERF");
env.remove_var("MC_TUI_PERF");
assert!(!TuiPerfCounters::from_env().enabled());
env.set_var("MC_TUI_PERF", "1");
assert!(TuiPerfCounters::from_env().enabled());
env.remove_var("MC_TUI_PERF");
env.set_var("MAGI_TUI_PERF", "1");
assert!(TuiPerfCounters::from_env().enabled());
env.remove_var("MAGI_TUI_PERF");
}
}
}
#[cfg(not(any(test, debug_assertions)))]
mod release {
#[inline(always)]
pub(crate) fn increment_projected_cards() {}
}
#[cfg(any(test, debug_assertions))]
pub(crate) use active::*;
#[cfg(not(any(test, debug_assertions)))]
pub(crate) use release::*;