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 fn into_recorded(self) -> crate::writer::types::RecordedInspectType {
23 crate::writer::types::RecordedInspectType::UintArray(self.array)
24 }
25}
26
27impl UintLinearHistogramProperty {
28 pub(crate) fn new(
29 name: Cow<'_, str>,
30 params: LinearHistogramParams<u64>,
31 parent: &Node,
32 ) -> Self {
33 let slots = params.buckets + ArrayFormat::LinearHistogram.extra_slots();
34 let array = parent.create_uint_array_internal(name, slots, ArrayFormat::LinearHistogram);
35 array.set(0, params.floor);
36 array.set(1, params.step_size);
37 Self { floor: params.floor, step_size: params.step_size, buckets: params.buckets, array }
38 }
39
40 fn get_index(&self, value: u64) -> usize {
41 let mut bucket_end = self.floor; let mut index = ArrayFormat::LinearHistogram.underflow_bucket_index();
43 let overflow_index = ArrayFormat::LinearHistogram.overflow_bucket_index(self.buckets);
44 while value >= bucket_end && index < overflow_index {
45 bucket_end = bucket_end.saturating_add(self.step_size);
46 index += 1;
47 }
48 index
49 }
50}
51
52impl HistogramProperty for UintLinearHistogramProperty {
53 type Type = u64;
54
55 fn insert(&self, value: u64) {
56 self.insert_multiple(value, 1);
57 }
58
59 fn insert_multiple(&self, value: u64, count: usize) {
60 self.array.add(self.get_index(value), count as u64);
61 }
62
63 fn clear(&self) {
64 if let Some(ref inner_ref) = self.array.inner.inner_ref() {
65 inner_ref
67 .state
68 .try_lock()
69 .and_then(|mut state| {
70 state.clear_array(
73 inner_ref.block_index,
74 ArrayFormat::LinearHistogram.underflow_bucket_index(),
75 )
76 })
77 .unwrap_or_else(|err| {
78 error!(err:?; "Failed to clear property");
79 });
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use crate::writer::Inspector;
88 use crate::writer::testing_utils::GetBlockExt;
89 use inspect_format::{Array, Uint};
90
91 #[fuchsia::test]
92 fn uint_linear_histogram() {
93 let inspector = Inspector::default();
94 let root = inspector.root();
95 let node = root.create_child("node");
96 {
97 let uint_histogram = node.create_uint_linear_histogram(
98 "uint-histogram",
99 LinearHistogramParams { floor: 10, step_size: 5, buckets: 5 },
100 );
101 uint_histogram.insert_multiple(0, 2); uint_histogram.insert(25);
103 uint_histogram.insert(500); uint_histogram.array.get_block::<_, Array<Uint>>(|block| {
105 for (i, value) in [10, 5, 2, 0, 0, 0, 1, 0, 1].iter().enumerate() {
106 assert_eq!(block.get(i).unwrap(), *value);
107 }
108 });
109
110 uint_histogram.clear();
111 uint_histogram.array.get_block::<_, Array<Uint>>(|block| {
112 for (i, value) in [10, 5, 0, 0, 0, 0, 0, 0, 0].iter().enumerate() {
113 assert_eq!(*value, block.get(i).unwrap());
114 }
115 });
116
117 node.get_block::<_, inspect_format::Node>(|node_block| {
118 assert_eq!(node_block.child_count(), 1);
119 });
120 }
121 node.get_block::<_, inspect_format::Node>(|node_block| {
122 assert_eq!(node_block.child_count(), 0);
123 });
124 }
125
126 #[fuchsia::test]
127 fn underflow() {
128 let inspector = Inspector::default();
129 let root = inspector.root();
130 let hist = root.create_uint_linear_histogram(
131 "test",
132 LinearHistogramParams { floor: 0, step_size: u64::MAX / 2, buckets: 4 },
133 );
134
135 hist.insert(0); hist.insert(u64::MAX / 2); hist.insert(u64::MAX); hist.array.get_block::<_, Array<Uint>>(|block| {
148 assert_eq!(block.get(0).unwrap(), 0);
149 assert_eq!(block.get(1).unwrap(), u64::MAX / 2);
150
151 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); });
158 }
159}