fuchsia_inspect/writer/types/
uint_linear_histogram.rs1use crate::writer::{
6 ArithmeticArrayProperty, ArrayProperty, HistogramProperty, InspectType, Node, UintArrayProperty,
7};
8use diagnostics_hierarchy::{ArrayFormat, LinearHistogramParams};
9use log::error;
10use std::borrow::Cow;
11
12#[derive(Debug, Default)]
13pub struct UintLinearHistogramProperty {
15 array: UintArrayProperty,
16 floor: u64,
17 buckets: usize,
18 step_size: u64,
19}
20
21impl InspectType for UintLinearHistogramProperty {}
22
23impl UintLinearHistogramProperty {
24 pub(crate) fn new(
25 name: Cow<'_, str>,
26 params: LinearHistogramParams<u64>,
27 parent: &Node,
28 ) -> Self {
29 let slots = params.buckets + ArrayFormat::LinearHistogram.extra_slots();
30 let array = parent.create_uint_array_internal(name, slots, ArrayFormat::LinearHistogram);
31 array.set(0, params.floor);
32 array.set(1, params.step_size);
33 Self { floor: params.floor, step_size: params.step_size, buckets: params.buckets, array }
34 }
35
36 fn get_index(&self, value: u64) -> usize {
37 let mut bucket_end = self.floor; let mut index = ArrayFormat::LinearHistogram.underflow_bucket_index();
39 let overflow_index = ArrayFormat::LinearHistogram.overflow_bucket_index(self.buckets);
40 while value >= bucket_end && index < overflow_index {
41 bucket_end = bucket_end.saturating_add(self.step_size);
42 index += 1;
43 }
44 index
45 }
46}
47
48impl HistogramProperty for UintLinearHistogramProperty {
49 type Type = u64;
50
51 fn insert(&self, value: u64) {
52 self.insert_multiple(value, 1);
53 }
54
55 fn insert_multiple(&self, value: u64, count: usize) {
56 self.array.add(self.get_index(value), count as u64);
57 }
58
59 fn clear(&self) {
60 if let Some(ref inner_ref) = self.array.inner.inner_ref() {
61 inner_ref
63 .state
64 .try_lock()
65 .and_then(|mut state| {
66 state.clear_array(
69 inner_ref.block_index,
70 ArrayFormat::LinearHistogram.underflow_bucket_index(),
71 )
72 })
73 .unwrap_or_else(|err| {
74 error!(err:?; "Failed to clear property");
75 });
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::writer::Inspector;
84 use crate::writer::testing_utils::GetBlockExt;
85 use inspect_format::{Array, Uint};
86
87 #[fuchsia::test]
88 fn uint_linear_histogram() {
89 let inspector = Inspector::default();
90 let root = inspector.root();
91 let node = root.create_child("node");
92 {
93 let uint_histogram = node.create_uint_linear_histogram(
94 "uint-histogram",
95 LinearHistogramParams { floor: 10, step_size: 5, buckets: 5 },
96 );
97 uint_histogram.insert_multiple(0, 2); uint_histogram.insert(25);
99 uint_histogram.insert(500); uint_histogram.array.get_block::<_, Array<Uint>>(|block| {
101 for (i, value) in [10, 5, 2, 0, 0, 0, 1, 0, 1].iter().enumerate() {
102 assert_eq!(block.get(i).unwrap(), *value);
103 }
104 });
105
106 uint_histogram.clear();
107 uint_histogram.array.get_block::<_, Array<Uint>>(|block| {
108 for (i, value) in [10, 5, 0, 0, 0, 0, 0, 0, 0].iter().enumerate() {
109 assert_eq!(*value, block.get(i).unwrap());
110 }
111 });
112
113 node.get_block::<_, inspect_format::Node>(|node_block| {
114 assert_eq!(node_block.child_count(), 1);
115 });
116 }
117 node.get_block::<_, inspect_format::Node>(|node_block| {
118 assert_eq!(node_block.child_count(), 0);
119 });
120 }
121
122 #[fuchsia::test]
123 fn underflow() {
124 let inspector = Inspector::default();
125 let root = inspector.root();
126 let hist = root.create_uint_linear_histogram(
127 "test",
128 LinearHistogramParams { floor: 0, step_size: u64::MAX / 2, buckets: 4 },
129 );
130
131 hist.insert(0); hist.insert(u64::MAX / 2); hist.insert(u64::MAX); hist.array.get_block::<_, Array<Uint>>(|block| {
144 assert_eq!(block.get(0).unwrap(), 0);
145 assert_eq!(block.get(1).unwrap(), u64::MAX / 2);
146
147 assert_eq!(block.get(2).unwrap(), 0); assert_eq!(block.get(3).unwrap(), 1); assert_eq!(block.get(4).unwrap(), 1); assert_eq!(block.get(5).unwrap(), 0); assert_eq!(block.get(6).unwrap(), 0); assert_eq!(block.get(7).unwrap(), 1); });
154 }
155}