use std::cell::Cell;
use std::sync::OnceLock;
use std::time::Instant;
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
pub(crate) struct Stages {
pub probe_us: u64,
pub index_read_us: u64,
pub index_parse_us: u64,
pub index_nodes: u64,
pub lookup_calls: u64,
pub dispatch_us: u64,
pub materialize_us: u64,
pub observe_us: u64,
}
impl Stages {
const ZERO: Stages = Stages {
probe_us: 0,
index_read_us: 0,
index_parse_us: 0,
index_nodes: 0,
lookup_calls: 0,
dispatch_us: 0,
materialize_us: 0,
observe_us: 0,
};
}
thread_local! {
static STAGES: Cell<Stages> = const { Cell::new(Stages::ZERO) };
}
#[inline]
pub(crate) fn enabled() -> bool {
static ON: OnceLock<bool> = OnceLock::new();
*ON.get_or_init(super::warm_prof_enabled)
}
fn update(f: impl FnOnce(&mut Stages)) {
STAGES.with(|s| {
let mut v = s.get();
f(&mut v);
s.set(v);
});
}
#[inline]
pub(crate) fn start() -> Option<Instant> {
enabled().then(Instant::now)
}
pub(crate) fn reset() {
if enabled() {
STAGES.with(|s| s.set(Stages::ZERO));
}
}
pub(crate) fn take() -> Stages {
STAGES.with(|s| {
let v = s.get();
s.set(Stages::ZERO);
v
})
}
#[inline]
pub(crate) fn add_probe(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.probe_us = v.probe_us.saturating_add(us(t)));
}
}
#[inline]
pub(crate) fn add_index_read(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.index_read_us = v.index_read_us.saturating_add(us(t)));
}
}
#[inline]
pub(crate) fn add_index_parse(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.index_parse_us = v.index_parse_us.saturating_add(us(t)));
}
}
#[inline]
pub(crate) fn inc_index_node() {
if enabled() {
update(|v| v.index_nodes = v.index_nodes.saturating_add(1));
}
}
#[inline]
pub(crate) fn inc_lookup() {
if enabled() {
update(|v| v.lookup_calls = v.lookup_calls.saturating_add(1));
}
}
#[inline]
pub(crate) fn add_dispatch(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.dispatch_us = v.dispatch_us.saturating_add(us(t)));
}
}
#[inline]
pub(crate) fn add_materialize(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.materialize_us = v.materialize_us.saturating_add(us(t)));
}
}
#[inline]
pub(crate) fn add_observe(t: Option<Instant>) {
if let Some(t) = t {
update(|v| v.observe_us = v.observe_us.saturating_add(us(t)));
}
}
#[inline]
fn us(t: Instant) -> u64 {
t.elapsed().as_micros().min(u128::from(u64::MAX)) as u64
}