mmtk/util/statistics/counter/
long_counter.rs1use 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(¤t_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>;