mmtk/util/statistics/counter/
mod.rs

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