metrics_util/storage/
histogram.rs1#[derive(Debug, Clone)]
11pub struct Histogram {
12 count: u64,
13 bounds: Vec<f64>,
14 buckets: Vec<u64>,
15 sum: f64,
16}
17
18impl Histogram {
19 pub fn new(bounds: &[f64]) -> Option<Histogram> {
23 if bounds.is_empty() {
24 return None;
25 }
26
27 let buckets = vec![0u64; bounds.len()];
28
29 Some(Histogram { count: 0, bounds: Vec::from(bounds), buckets, sum: 0.0 })
30 }
31
32 pub fn sum(&self) -> f64 {
34 self.sum
35 }
36
37 pub fn count(&self) -> u64 {
39 self.count
40 }
41
42 pub fn buckets(&self) -> Vec<(f64, u64)> {
47 self.bounds.iter().cloned().zip(self.buckets.iter().cloned()).collect()
48 }
49
50 pub fn record(&mut self, sample: f64) {
52 self.sum += sample;
53 self.count += 1;
54
55 for (idx, bucket) in self.bounds.iter().enumerate() {
57 if sample <= *bucket {
58 self.buckets[idx] += 1;
59 }
60 }
61 }
62
63 pub fn record_many<'a, S>(&mut self, samples: S)
65 where
66 S: IntoIterator<Item = &'a f64> + 'a,
67 {
68 let mut bucketed = vec![0u64; self.buckets.len()];
69
70 let mut sum = 0.0;
71 let mut count = 0;
72 for sample in samples.into_iter() {
73 sum += *sample;
74 count += 1;
75
76 for (idx, bucket) in self.bounds.iter().enumerate() {
77 if sample <= bucket {
78 bucketed[idx] += 1;
79 break;
80 }
81 }
82 }
83
84 if bucketed.len() >= 2 {
87 for idx in 0..(bucketed.len() - 1) {
88 bucketed[idx + 1] += bucketed[idx];
89 }
90 }
91
92 for (idx, local) in bucketed.iter().enumerate() {
94 self.buckets[idx] += local;
95 }
96 self.sum += sum;
97 self.count += count;
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::Histogram;
104
105 #[test]
106 fn test_histogram() {
107 let histogram = Histogram::new(&[]);
109 assert!(histogram.is_none());
110
111 let buckets = &[10.0, 25.0, 100.0];
112 let values = vec![3.0, 2.0, 6.0, 12.0, 56.0, 82.0, 202.0, 100.0, 29.0];
113
114 let mut histogram = Histogram::new(buckets).expect("histogram should have been created");
115
116 histogram.record_many(&values);
117 histogram.record(89.0);
118
119 let result = histogram.buckets();
120 assert_eq!(result.len(), 3);
121
122 let (_, first) = result[0];
123 assert_eq!(first, 3);
124 let (_, second) = result[1];
125 assert_eq!(second, 4);
126 let (_, third) = result[2];
127 assert_eq!(third, 9);
128
129 assert_eq!(histogram.count(), values.len() as u64 + 1);
130 assert_eq!(histogram.sum(), 581.0);
131 }
132}