mmtk/util/statistics/counter/
event_counter.rs

1use super::*;
2use crate::util::statistics::stats::{SharedStats, DEFAULT_NUM_PHASES};
3use std::sync::Arc;
4
5/**
6 * This file implements a simple event counter (counting number
7 * events that occur for each phase).
8 */
9pub struct EventCounter {
10    name: String,
11    pub implicitly_start: bool,
12    merge_phases: bool,
13    /// The raw per-phase counts, in phase order (index 0 = phase 0, etc). Visible within the
14    /// `counter` module so [`super::LatencySampler`] can compute derived statistics.
15    pub(super) count: Vec<u64>,
16    current_count: u64,
17    running: bool,
18    stats: Arc<SharedStats>,
19}
20
21impl EventCounter {
22    pub fn new(
23        name: String,
24        stats: Arc<SharedStats>,
25        implicitly_start: bool,
26        merge_phases: bool,
27    ) -> Self {
28        EventCounter {
29            name,
30            implicitly_start,
31            merge_phases,
32            count: Vec::with_capacity(DEFAULT_NUM_PHASES),
33            current_count: 0,
34            running: false,
35            stats,
36        }
37    }
38
39    /**
40     * Increment the event counter
41     */
42    pub fn inc(&mut self) {
43        if self.running {
44            self.inc_by(1);
45        }
46    }
47
48    /**
49     * Increment the event counter by provided value
50     */
51    pub fn inc_by(&mut self, value: u64) {
52        if self.running {
53            self.current_count += value;
54        }
55    }
56
57    pub fn print_current(&self) {
58        self.print_value(self.current_count);
59    }
60
61    fn print_value(&self, value: u64) {
62        print!("{}", value);
63    }
64}
65
66impl Counter for EventCounter {
67    fn start(&mut self) {
68        if !self.stats.get_gathering_stats() {
69            return;
70        }
71        debug_assert!(!self.running);
72        self.current_count = 0;
73        self.running = true;
74    }
75
76    fn stop(&mut self) {
77        if !self.stats.get_gathering_stats() {
78            return;
79        }
80        debug_assert!(self.running);
81        self.count.push(self.current_count);
82        debug_assert_eq!(self.count[self.stats.get_phase()], self.current_count);
83        self.running = false;
84    }
85
86    fn phase_change(&mut self, old_phase: usize) {
87        if self.running {
88            self.count.push(self.current_count);
89            debug_assert_eq!(self.count[old_phase], self.current_count);
90            self.current_count = 0;
91        }
92    }
93
94    fn print_count(&self, phase: usize) {
95        if self.merge_phases() {
96            debug_assert!((phase | 1) == (phase + 1));
97            self.print_value(self.count[phase] + self.count[phase + 1]);
98        } else {
99            self.print_value(self.count[phase]);
100        }
101    }
102
103    fn get_total(&self, other: Option<bool>) -> u64 {
104        match other {
105            None => {
106                let mut total = 0;
107                for p in 0..=self.stats.get_phase() {
108                    total += self.count[p];
109                }
110                total
111            }
112            Some(m) => {
113                let mut total = 0;
114                let mut p = !m as usize;
115                while p <= self.stats.get_phase() {
116                    total += self.count[p];
117                    p += 2;
118                }
119                total
120            }
121        }
122    }
123
124    fn print_total(&self, other: Option<bool>) {
125        self.print_value(self.get_total(other));
126    }
127
128    fn print_min(&self, other: bool) {
129        let mut p = !other as usize;
130        let mut min = self.count[p];
131        while p < self.stats.get_phase() {
132            if self.count[p] < min {
133                min = self.count[p];
134                p += 2;
135            }
136        }
137        self.print_value(min);
138    }
139
140    fn print_max(&self, other: bool) {
141        let mut p = !other as usize;
142        let mut max = self.count[p];
143        while p < self.stats.get_phase() {
144            if self.count[p] > max {
145                max = self.count[p];
146                p += 2;
147            }
148        }
149        self.print_value(max);
150    }
151
152    fn print_last(&self) {
153        let phase = self.stats.get_phase();
154        if phase > 0 {
155            self.print_count(phase - 1);
156        }
157    }
158
159    fn merge_phases(&self) -> bool {
160        self.merge_phases
161    }
162
163    fn implicitly_start(&self) -> bool {
164        self.implicitly_start
165    }
166
167    fn name(&self) -> &String {
168        &self.name
169    }
170}