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}