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}