midenc_session/
statistics.rs

1use std::{
2    fmt,
3    sync::atomic::{AtomicU64, Ordering},
4    time::{Duration, Instant},
5};
6
7use crate::HumanDuration;
8
9const NOT_STARTED: u64 = u64::MAX;
10
11/// This struct contains various statistics about a compilation session
12pub struct Statistics {
13    /// The time at which the compiler session started
14    start_time: Instant,
15    /// The elapsed time at which parsing started
16    ///
17    /// Parsing here refers to one of two things:
18    ///
19    /// 1. Loading of a Wasm module into memory and converting it to HIR
20    /// 2. Parsing of an HIR module into memory
21    parse_time: AtomicU64,
22    /// The elapsed time at which optimizations/rewrites started
23    opt_time: AtomicU64,
24    /// The elapsed time at which codegen started
25    codegen_time: AtomicU64,
26}
27impl fmt::Debug for Statistics {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.debug_struct("Statistics")
30            .field("elapsed", &self.elapsed())
31            .field("parsing", &self.parse_time())
32            .field("optimization", &self.opt_time())
33            .field("codegen", &self.codegen_time())
34            .finish()
35    }
36}
37impl Default for Statistics {
38    fn default() -> Statistics {
39        Self::new(Instant::now())
40    }
41}
42impl Statistics {
43    pub fn new(start_time: Instant) -> Self {
44        Self {
45            start_time,
46            parse_time: AtomicU64::new(NOT_STARTED),
47            opt_time: AtomicU64::new(NOT_STARTED),
48            codegen_time: AtomicU64::new(NOT_STARTED),
49        }
50    }
51
52    /// Get the duration since the compiler session started
53    pub fn elapsed(&self) -> HumanDuration {
54        HumanDuration::since(self.start_time)
55    }
56
57    /// Get the time spent parsing/loading inputs, if applicable
58    pub fn parse_time(&self) -> Option<HumanDuration> {
59        load_duration(&self.parse_time)
60    }
61
62    /// Get the time spent optimizing the IR, if applicable
63    pub fn opt_time(&self) -> Option<HumanDuration> {
64        load_duration(&self.opt_time)
65    }
66
67    /// Get the time spent generating Miden Assembly, if applicable
68    pub fn codegen_time(&self) -> Option<HumanDuration> {
69        load_duration(&self.codegen_time)
70    }
71
72    /// Record that parsing/loading inputs has completed
73    pub fn parsing_completed(&self) {
74        store_duration(&self.parse_time, self.elapsed())
75    }
76
77    /// Record that optimization of the IR has completed
78    pub fn optimization_completed(&self) {
79        store_duration(&self.opt_time, self.elapsed())
80    }
81
82    /// Record that codegen of Miden Assembly has completed
83    pub fn codegen_completed(&self) {
84        store_duration(&self.codegen_time, self.elapsed())
85    }
86}
87
88fn store_duration(raw_secs_f64: &AtomicU64, duration: HumanDuration) {
89    let bits = duration.as_secs_f64().to_bits();
90    raw_secs_f64.store(bits, Ordering::Relaxed)
91}
92
93fn load_duration(raw_secs_f64: &AtomicU64) -> Option<HumanDuration> {
94    match raw_secs_f64.load(Ordering::Relaxed) {
95        NOT_STARTED => None,
96        bits => Some(Duration::from_secs_f64(f64::from_bits(bits)).into()),
97    }
98}