use std::{
fmt,
sync::atomic::{AtomicU64, Ordering},
time::{Duration, Instant},
};
use crate::HumanDuration;
const NOT_STARTED: u64 = u64::MAX;
pub struct Statistics {
start_time: Instant,
parse_time: AtomicU64,
opt_time: AtomicU64,
codegen_time: AtomicU64,
}
impl fmt::Debug for Statistics {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Statistics")
.field("elapsed", &self.elapsed())
.field("parsing", &self.parse_time())
.field("optimization", &self.opt_time())
.field("codegen", &self.codegen_time())
.finish()
}
}
impl Default for Statistics {
fn default() -> Statistics {
Self::new(Instant::now())
}
}
impl Statistics {
pub fn new(start_time: Instant) -> Self {
Self {
start_time,
parse_time: AtomicU64::new(NOT_STARTED),
opt_time: AtomicU64::new(NOT_STARTED),
codegen_time: AtomicU64::new(NOT_STARTED),
}
}
pub fn elapsed(&self) -> HumanDuration {
HumanDuration::since(self.start_time)
}
pub fn parse_time(&self) -> Option<HumanDuration> {
load_duration(&self.parse_time)
}
pub fn opt_time(&self) -> Option<HumanDuration> {
load_duration(&self.opt_time)
}
pub fn codegen_time(&self) -> Option<HumanDuration> {
load_duration(&self.codegen_time)
}
pub fn parsing_completed(&self) {
store_duration(&self.parse_time, self.elapsed())
}
pub fn optimization_completed(&self) {
store_duration(&self.opt_time, self.elapsed())
}
pub fn codegen_completed(&self) {
store_duration(&self.codegen_time, self.elapsed())
}
}
fn store_duration(raw_secs_f64: &AtomicU64, duration: HumanDuration) {
let bits = duration.as_secs_f64().to_bits();
raw_secs_f64.store(bits, Ordering::Relaxed)
}
fn load_duration(raw_secs_f64: &AtomicU64) -> Option<HumanDuration> {
match raw_secs_f64.load(Ordering::Relaxed) {
NOT_STARTED => None,
bits => Some(Duration::from_secs_f64(f64::from_bits(bits)).into()),
}
}