1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::{sync::atomic::Ordering, time::Instant};

use atomic_float::AtomicF64;

/// Tracks the total time spent applying transactions.
pub static STAT_APPLY_SECS: StatCounter = StatCounter {
    counter: AtomicF64::new(0.0),
};

/// Tracks the total time spent obtaining values from SMTs.
pub static STAT_SMT_GET_SECS: StatCounter = StatCounter {
    counter: AtomicF64::new(0.0),
};

/// Tracks the total time spent inserting values into SMTs.
pub static STAT_SMT_INSERT_SECS: StatCounter = StatCounter {
    counter: AtomicF64::new(0.0),
};

/// Tracks the total time spent validating covenants.
pub static STAT_MELVM_RUNTIME_SECS: StatCounter = StatCounter {
    counter: AtomicF64::new(0.0),
};

/// Tracks the total time spent validating melpow proofs.
pub static STAT_MELPOW_SECS: StatCounter = StatCounter {
    counter: AtomicF64::new(0.0),
};

/// Statistics counter. Tracks some floating-point metric.
pub struct StatCounter {
    counter: AtomicF64,
}

impl StatCounter {
    /// Reads the value out.
    pub fn value(&self) -> f64 {
        self.counter.load(Ordering::Relaxed)
    }

    /// Increments this stat by some number.
    pub(crate) fn incr(&self, delta: f64) {
        self.counter.fetch_add(delta, Ordering::Relaxed);
    }

    /// Create a duration-based timer.
    pub(crate) fn timer_secs(&self) -> StatTimer<'_> {
        StatTimer {
            r: self,
            start: Instant::now(),
        }
    }
}

/// A timer that increments the statistic when dropped
pub struct StatTimer<'a> {
    r: &'a StatCounter,
    start: Instant,
}

impl<'a> Drop for StatTimer<'a> {
    fn drop(&mut self) {
        self.r.incr(self.start.elapsed().as_secs_f64())
    }
}