mmtk/util/statistics/counter/
long_counter.rs

1use super::*;
2use crate::util::statistics::stats::{SharedStats, DEFAULT_NUM_PHASES};
3use std::fmt;
4use std::sync::Arc;
5
6pub struct LongCounter<T: Diffable> {
7    name: String,
8    pub implicitly_start: bool,
9    merge_phases: bool,
10    count: Vec<u64>,
11    diffable: T,
12    start_value: Option<T::Val>,
13    total_count: u64,
14    running: bool,
15    stats: Arc<SharedStats>,
16}
17
18impl<T: Diffable> fmt::Debug for LongCounter<T> {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        write!(f, "LongCounter({})", self.name)
21    }
22}
23
24impl<T: Diffable> Counter for LongCounter<T> {
25    fn start(&mut self) {
26        if !self.stats.get_gathering_stats() {
27            return;
28        }
29        debug_assert!(!self.running);
30        self.running = true;
31        self.diffable.start();
32        self.start_value = Some(self.diffable.current_value());
33    }
34
35    fn stop(&mut self) {
36        if !self.stats.get_gathering_stats() {
37            return;
38        }
39        debug_assert!(self.running);
40        self.running = false;
41        self.diffable.stop();
42        let current_value = self.diffable.current_value();
43        let delta = T::diff(&current_value, self.start_value.as_ref().unwrap());
44        self.count.push(delta);
45        debug_assert_eq!(self.count[self.stats.get_phase()], delta);
46        self.total_count += delta;
47    }
48
49    fn phase_change(&mut self, old_phase: usize) {
50        if self.running {
51            let now = self.diffable.current_value();
52            let delta = T::diff(&now, self.start_value.as_ref().unwrap());
53            self.count.push(delta);
54            debug_assert_eq!(self.count[old_phase], delta);
55            self.total_count += delta;
56            self.start_value = Some(now);
57        }
58    }
59
60    fn print_count(&self, phase: usize) {
61        if self.merge_phases() {
62            debug_assert!((phase | 1) == (phase + 1));
63            self.print_value(self.count[phase] + self.count[phase + 1]);
64        } else {
65            self.print_value(self.count[phase]);
66        }
67    }
68
69    fn get_total(&self, other: Option<bool>) -> u64 {
70        match other {
71            None => self.total_count,
72            Some(m) => {
73                let mut total = 0;
74                let mut p = !m as usize;
75                while p <= self.stats.get_phase() {
76                    total += self.count[p];
77                    p += 2;
78                }
79                total
80            }
81        }
82    }
83
84    fn print_total(&self, other: Option<bool>) {
85        self.print_value(self.get_total(other));
86    }
87
88    fn print_min(&self, other: bool) {
89        let mut p = !other as usize;
90        let mut min = self.count[p];
91        while p < self.stats.get_phase() {
92            if self.count[p] < min {
93                min = self.count[p];
94                p += 2;
95            }
96        }
97        self.print_value(min);
98    }
99
100    fn print_max(&self, other: bool) {
101        let mut p = !other as usize;
102        let mut max = self.count[p];
103        while p < self.stats.get_phase() {
104            if self.count[p] > max {
105                max = self.count[p];
106                p += 2;
107            }
108        }
109        self.print_value(max);
110    }
111
112    fn print_last(&self) {
113        let phase = self.stats.get_phase();
114        if phase > 0 {
115            self.print_count(phase - 1);
116        }
117    }
118
119    fn merge_phases(&self) -> bool {
120        self.merge_phases
121    }
122
123    fn implicitly_start(&self) -> bool {
124        self.implicitly_start
125    }
126
127    fn name(&self) -> &String {
128        &self.name
129    }
130}
131
132impl<T: Diffable> LongCounter<T> {
133    pub fn new(
134        name: String,
135        stats: Arc<SharedStats>,
136        implicitly_start: bool,
137        merge_phases: bool,
138        diffable: T,
139    ) -> Self {
140        LongCounter {
141            name,
142            implicitly_start,
143            merge_phases,
144            count: Vec::with_capacity(DEFAULT_NUM_PHASES),
145            diffable,
146            start_value: None,
147            total_count: 0,
148            running: false,
149            stats,
150        }
151    }
152
153    fn print_value(&self, val: u64) {
154        T::print_diff(val);
155    }
156}
157
158pub type Timer = LongCounter<MonotoneNanoTime>;