Skip to content

Commit a813ba0

Browse files
committed
feat: add metrics counter utility
1 parent f2172db commit a813ba0

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/cargo/util/counter.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::time::Instant;
2+
3+
/// A metrics counter storing only latest `N` records.
4+
pub struct MetricsCounter<const N: usize> {
5+
/// Slots to store metrics.
6+
slots: [(usize, Instant); N],
7+
/// The slot of the oldest record.
8+
/// Also the next slot to store the new record.
9+
index: usize,
10+
}
11+
12+
impl<const N: usize> MetricsCounter<N> {
13+
/// Creates a new counter with an initial value.
14+
pub fn new(init: usize) -> Self {
15+
debug_assert!(N > 0, "number of slots must be greater than zero");
16+
Self {
17+
slots: [(init, Instant::now()); N],
18+
index: 0,
19+
}
20+
}
21+
22+
/// Adds record to the counter.
23+
pub fn add(&mut self, data: usize) {
24+
self.slots[self.index] = (data, Instant::now());
25+
self.index = (self.index + 1) % N;
26+
}
27+
28+
/// Calculates per-second average rate of all slots.
29+
pub fn rate(&self) -> f32 {
30+
let latest = self.slots[self.index.checked_sub(1).unwrap_or(N - 1)];
31+
let oldest = self.slots[self.index];
32+
let duration = (latest.1 - oldest.1).as_secs_f32();
33+
let avg = (latest.0 - oldest.0) as f32 / duration;
34+
if f32::is_nan(avg) {
35+
0f32
36+
} else {
37+
avg
38+
}
39+
}
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::MetricsCounter;
45+
46+
#[test]
47+
fn counter() {
48+
let mut counter = MetricsCounter::<3>::new(0);
49+
assert_eq!(counter.rate(), 0f32);
50+
for i in 1..=5 {
51+
counter.add(i);
52+
assert!(counter.rate() > 0f32);
53+
}
54+
}
55+
56+
#[test]
57+
#[should_panic(expected = "number of slots must be greater than zero")]
58+
fn counter_zero_slot() {
59+
let _counter = MetricsCounter::<0>::new(0);
60+
}
61+
}

src/cargo/util/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::time::Duration;
33

44
pub use self::canonical_url::CanonicalUrl;
55
pub use self::config::{homedir, Config, ConfigValue};
6+
pub(crate) use self::counter::MetricsCounter;
67
pub use self::dependency_queue::DependencyQueue;
78
pub use self::diagnostic_server::RustfixDiagnosticServer;
89
pub use self::errors::{internal, CargoResult, CliResult, Test};
@@ -29,6 +30,7 @@ pub use self::workspace::{
2930
mod canonical_url;
3031
pub mod command_prelude;
3132
pub mod config;
33+
mod counter;
3234
pub mod cpu;
3335
mod dependency_queue;
3436
pub mod diagnostic_server;

0 commit comments

Comments
 (0)