#[cfg(feature = "profile")]
mod imp {
use std::cell::RefCell;
use std::time::Instant;
pub const STAGES: &[&str] = &[
"enc.filter",
"enc.deflate",
"enc.chunk",
"dec.inflate",
"dec.unfilter",
"dec.transform",
"enc.finish",
"enc.crc",
];
thread_local! {
static ACC: RefCell<[(f64, u64); 8]> = const { RefCell::new([(0.0, 0); 8]) };
}
pub struct Scope {
idx: usize,
start: Instant,
}
impl Scope {
#[inline]
pub fn new(idx: usize) -> Self {
Scope {
idx,
start: Instant::now(),
}
}
}
impl Drop for Scope {
#[inline]
fn drop(&mut self) {
let ns = self.start.elapsed().as_nanos() as f64;
let i = self.idx;
ACC.with(|a| {
let mut a = a.borrow_mut();
a[i].0 += ns;
a[i].1 += 1;
});
}
}
pub fn reset() {
ACC.with(|a| *a.borrow_mut() = [(0.0, 0); 8]);
}
pub fn dump() -> Vec<(&'static str, f64, u64)> {
ACC.with(|a| {
let a = a.borrow();
STAGES
.iter()
.enumerate()
.filter(|(i, _)| a[*i].1 > 0)
.map(|(i, name)| (*name, a[i].0 / 1e6, a[i].1))
.collect()
})
}
}
#[cfg(not(feature = "profile"))]
mod imp {
pub const STAGES: &[&str] = &[];
pub struct Scope;
impl Scope {
#[inline(always)]
pub fn new(_idx: usize) -> Self {
Scope
}
}
pub fn reset() {}
pub fn dump() -> Vec<(&'static str, f64, u64)> {
Vec::new()
}
}
pub use imp::{dump, reset, Scope, STAGES};
pub const ENC_FILTER: usize = 0;
pub const ENC_DEFLATE: usize = 1;
pub const ENC_CHUNK: usize = 2;
pub const DEC_INFLATE: usize = 3;
pub const DEC_UNFILTER: usize = 4;
pub const DEC_TRANSFORM: usize = 5;
pub const ENC_FINISH: usize = 6;
pub const ENC_CRC: usize = 7;
#[macro_export]
macro_rules! prof_scope {
($idx:expr) => {
let _rusty_png_scope = $crate::prof::Scope::new($idx);
};
}