midenc_session/
statistics.rs1use 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
11pub struct Statistics {
13 start_time: Instant,
15 parse_time: AtomicU64,
22 opt_time: AtomicU64,
24 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 Clone for Statistics {
43 fn clone(&self) -> Self {
44 Self {
45 start_time: self.start_time,
46 parse_time: AtomicU64::new(self.parse_time.load(Ordering::Relaxed)),
47 opt_time: AtomicU64::new(self.opt_time.load(Ordering::Relaxed)),
48 codegen_time: AtomicU64::new(self.codegen_time.load(Ordering::Relaxed)),
49 }
50 }
51}
52impl Statistics {
53 pub fn new(start_time: Instant) -> Self {
54 Self {
55 start_time,
56 parse_time: AtomicU64::new(NOT_STARTED),
57 opt_time: AtomicU64::new(NOT_STARTED),
58 codegen_time: AtomicU64::new(NOT_STARTED),
59 }
60 }
61
62 pub fn elapsed(&self) -> HumanDuration {
64 HumanDuration::since(self.start_time)
65 }
66
67 pub fn parse_time(&self) -> Option<HumanDuration> {
69 load_duration(&self.parse_time)
70 }
71
72 pub fn opt_time(&self) -> Option<HumanDuration> {
74 load_duration(&self.opt_time)
75 }
76
77 pub fn codegen_time(&self) -> Option<HumanDuration> {
79 load_duration(&self.codegen_time)
80 }
81
82 pub fn parsing_completed(&self) {
84 store_duration(&self.parse_time, self.elapsed())
85 }
86
87 pub fn optimization_completed(&self) {
89 store_duration(&self.opt_time, self.elapsed())
90 }
91
92 pub fn codegen_completed(&self) {
94 store_duration(&self.codegen_time, self.elapsed())
95 }
96}
97
98fn store_duration(raw_secs_f64: &AtomicU64, duration: HumanDuration) {
99 let bits = duration.as_secs_f64().to_bits();
100 raw_secs_f64.store(bits, Ordering::Relaxed)
101}
102
103fn load_duration(raw_secs_f64: &AtomicU64) -> Option<HumanDuration> {
104 match raw_secs_f64.load(Ordering::Relaxed) {
105 NOT_STARTED => None,
106 bits => Some(Duration::from_secs_f64(f64::from_bits(bits)).into()),
107 }
108}