mmtk/util/statistics/counter/mod.rs
1use std::time::Instant;
2
3mod event_counter;
4mod long_counter;
5#[cfg(feature = "perf_counter")]
6mod perf_event;
7mod size_counter;
8
9pub use self::event_counter::EventCounter;
10pub use self::long_counter::{LongCounter, Timer};
11#[cfg(feature = "perf_counter")]
12pub use self::perf_event::PerfEventDiffable;
13pub use self::size_counter::SizeCounter;
14
15/// An abstraction over how a specific Diffable value is counted
16///
17/// For example, we can just collect the values, and store the cummulative sum,
18/// or we can derive some kind of histogram, etc.
19pub trait Counter {
20 /// Start the counter
21 fn start(&mut self);
22 /// Stop the counter
23 fn stop(&mut self);
24 /// Signal a change in GC phase.
25 ///
26 /// The phase number starts from 0 and is strictly increasing.
27 /// Even numbers mean mutators are running (`other`) while odd numbers mean
28 /// stop-the-world pauses (`stw`).
29 /// Take action with respect to the last phase if necessary.
30 fn phase_change(&mut self, old_phase: usize);
31 /// Print the counter value for a particular phase
32 ///
33 /// If the counter merges the phases, the printing value will include
34 /// the specified phase and the next phase
35 fn print_count(&self, phase: usize);
36 /// Get the total count over past phases
37 ///
38 /// If the argument is None, count all phases.
39 /// Otherwise, count only `other` phases if true, or `stw` phases if false
40 fn get_total(&self, other: Option<bool>) -> u64;
41 /// Print the total count over past phases
42 ///
43 /// If the argument is None, count all phases.
44 /// Otherwise, count only `other` phases if true, or `stw` phases if false
45 fn print_total(&self, other: Option<bool>);
46 /// Print the minimum count of the past phases
47 ///
48 /// Consider only `other` phases if true, or `stw` phases if false
49 fn print_min(&self, other: bool);
50 /// Print the maximum count of the past phases
51 ///
52 /// Consider only `other` phases if true, or `stw` phases if false
53 fn print_max(&self, other: bool);
54 /// Print the count of the last phases
55 fn print_last(&self);
56 /// Whether the counter merges other and stw phases.
57 fn merge_phases(&self) -> bool;
58 /// Whether the counter starts implicitly after creation
59 ///
60 /// FIXME currently unused
61 fn implicitly_start(&self) -> bool;
62 /// Get the name of the counter
63 fn name(&self) -> &String;
64}
65
66/// An abstraction over some changing values that we want to measure.
67///
68/// A Diffable object could be stateless (e.g. a timer that reads the wall
69/// clock), or stateful (e.g. holds reference to a perf event fd)
70pub trait Diffable {
71 /// The type of each reading
72 type Val;
73 /// Start the Diffable
74 fn start(&mut self);
75 /// Stop the Diffable
76 fn stop(&mut self);
77 /// Read the current value
78 fn current_value(&mut self) -> Self::Val;
79 /// Compute the difference between two readings
80 fn diff(current: &Self::Val, earlier: &Self::Val) -> u64;
81 /// Print the difference in a specific format
82 fn print_diff(val: u64);
83}
84
85pub struct MonotoneNanoTime;
86
87impl Diffable for MonotoneNanoTime {
88 type Val = Instant;
89
90 /// nop for the wall-clock time
91 fn start(&mut self) {}
92
93 /// nop for the wall-clock time
94 fn stop(&mut self) {}
95
96 fn current_value(&mut self) -> Instant {
97 Instant::now()
98 }
99
100 fn diff(current: &Instant, earlier: &Instant) -> u64 {
101 let delta = current.duration_since(*earlier);
102 delta.as_secs() * 1_000_000_000 + u64::from(delta.subsec_nanos())
103 }
104
105 fn print_diff(val: u64) {
106 print!("{:.*}", 2, val as f64 / 1e6f64);
107 }
108}