subms_hdr_histogram/features/
iterators.rs1use crate::{HdrHistogram, value_from_index};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct IterEntry {
20 pub value_lo: u64,
22 pub value_hi: u64,
25 pub count: u64,
27 pub cumulative: u64,
29}
30
31pub struct HdrLinearIter<'a> {
33 counters: &'a [u64],
34 sub_count_bits: u32,
35 high_index: usize,
36 idx: usize,
37 cumulative: u64,
38}
39
40impl<'a> HdrLinearIter<'a> {
41 pub(crate) fn new(h: &'a HdrHistogram) -> Self {
42 Self {
43 counters: h.counters(),
44 sub_count_bits: h.sub_count_bits(),
45 high_index: h.high_index(),
46 idx: 0,
47 cumulative: 0,
48 }
49 }
50}
51
52impl<'a> Iterator for HdrLinearIter<'a> {
53 type Item = IterEntry;
54 fn next(&mut self) -> Option<Self::Item> {
55 let bits = self.sub_count_bits;
56 let end = (self.high_index + 1).min(self.counters.len());
57 while self.idx < end {
58 let i = self.idx;
59 self.idx += 1;
60 let c = self.counters[i];
61 if c == 0 {
62 continue;
63 }
64 let lo = value_from_index(i, bits);
65 let hi = value_from_index(i + 1, bits);
66 self.cumulative += c;
67 return Some(IterEntry {
68 value_lo: lo,
69 value_hi: hi,
70 count: c,
71 cumulative: self.cumulative,
72 });
73 }
74 None
75 }
76}
77
78pub struct HdrLogarithmicIter<'a> {
81 counters: &'a [u64],
82 sub_count_bits: u32,
83 high_index: usize,
84 lo: u64,
86 cumulative: u64,
87 done: bool,
89}
90
91impl<'a> HdrLogarithmicIter<'a> {
92 pub(crate) fn new(h: &'a HdrHistogram) -> Self {
93 Self {
94 counters: h.counters(),
95 sub_count_bits: h.sub_count_bits(),
96 high_index: h.high_index(),
97 lo: 1,
98 cumulative: 0,
99 done: false,
100 }
101 }
102}
103
104impl<'a> Iterator for HdrLogarithmicIter<'a> {
105 type Item = IterEntry;
106 fn next(&mut self) -> Option<Self::Item> {
107 if self.done {
108 return None;
109 }
110 let bits = self.sub_count_bits;
111 let hi = self.lo.saturating_mul(2);
112 let mut count = 0u64;
114 let end = (self.high_index + 1).min(self.counters.len());
115 for i in 0..end {
116 let v = value_from_index(i, bits);
117 if v >= self.lo && v < hi {
118 count += self.counters[i];
119 }
120 }
121 self.cumulative += count;
122 let entry = IterEntry {
123 value_lo: self.lo,
124 value_hi: hi,
125 count,
126 cumulative: self.cumulative,
127 };
128 let high_val = value_from_index(self.high_index, bits);
130 if hi > high_val {
131 self.done = true;
132 }
133 self.lo = hi;
134 Some(entry)
135 }
136}
137
138pub struct HdrPercentileIter<'a> {
141 counters: &'a [u64],
142 sub_count_bits: u32,
143 high_index: usize,
144 total: u64,
145 step_pct: f64,
147 next_pct: f64,
149 idx: usize,
151 cum: u64,
153}
154
155impl<'a> HdrPercentileIter<'a> {
156 pub(crate) fn new(h: &'a HdrHistogram, step_percent: f64) -> Self {
157 Self {
158 counters: h.counters(),
159 sub_count_bits: h.sub_count_bits(),
160 high_index: h.high_index(),
161 total: h.count(),
162 step_pct: step_percent.max(f64::MIN_POSITIVE),
163 next_pct: step_percent.max(f64::MIN_POSITIVE),
164 idx: 0,
165 cum: 0,
166 }
167 }
168}
169
170impl<'a> Iterator for HdrPercentileIter<'a> {
171 type Item = IterEntry;
172 fn next(&mut self) -> Option<Self::Item> {
173 if self.total == 0 || self.next_pct > 100.0 + 1e-9 {
174 return None;
175 }
176 let bits = self.sub_count_bits;
177 let end = (self.high_index + 1).min(self.counters.len());
178 let target = ((self.next_pct / 100.0) * self.total as f64) as u64;
179 while self.idx < end {
181 self.cum += self.counters[self.idx];
182 if self.cum >= target {
183 let lo = value_from_index(self.idx, bits);
184 let hi = value_from_index(self.idx + 1, bits);
185 let pct_now = self.next_pct;
186 self.next_pct += self.step_pct;
187 return Some(IterEntry {
191 value_lo: lo,
192 value_hi: hi,
193 count: self.counters[self.idx],
194 cumulative: self
195 .cum
196 .min(self.total)
197 .max((pct_now / 100.0 * self.total as f64) as u64),
198 });
199 }
200 self.idx += 1;
201 }
202 None
203 }
204}
205
206impl HdrHistogram {
207 pub fn iter_linear(&self) -> HdrLinearIter<'_> {
208 HdrLinearIter::new(self)
209 }
210
211 pub fn iter_logarithmic(&self) -> HdrLogarithmicIter<'_> {
212 HdrLogarithmicIter::new(self)
213 }
214
215 pub fn iter_percentiles(&self, step_percent: f64) -> HdrPercentileIter<'_> {
216 HdrPercentileIter::new(self, step_percent)
217 }
218}
219
220#[cfg(test)]
221#[path = "iterators_tests.rs"]
222mod tests;