cbtop/bricks/analyzers/
throughput.rs1use crate::brick::{Brick, BrickAssertion, BrickBudget, BrickVerification};
4use std::any::Any;
5
6pub struct ThroughputAnalyzerBrick {
11 samples: Vec<f64>,
12 arrival_rate: f64,
13 avg_latency_ms: f64,
14}
15
16impl ThroughputAnalyzerBrick {
17 pub fn new() -> Self {
18 Self {
19 samples: Vec::new(),
20 arrival_rate: 0.0,
21 avg_latency_ms: 0.0,
22 }
23 }
24
25 pub fn analyze(&mut self, ops_per_sec: f64, latency_ms: f64) -> ThroughputResult {
26 self.arrival_rate = ops_per_sec;
27 self.avg_latency_ms = latency_ms;
28
29 let items_in_system = ops_per_sec * (latency_ms / 1000.0);
31
32 ThroughputResult {
33 ops_per_sec,
34 latency_ms,
35 items_in_system,
36 is_saturated: items_in_system > 1.0,
37 }
38 }
39
40 pub fn reset(&mut self) {
41 self.samples.clear();
42 self.arrival_rate = 0.0;
43 self.avg_latency_ms = 0.0;
44 }
45}
46
47#[derive(Debug, Clone)]
48pub struct ThroughputResult {
49 pub ops_per_sec: f64,
50 pub latency_ms: f64,
51 pub items_in_system: f64,
52 pub is_saturated: bool,
53}
54
55impl Default for ThroughputAnalyzerBrick {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl Brick for ThroughputAnalyzerBrick {
62 fn brick_name(&self) -> &'static str {
63 "throughput_analyzer"
64 }
65
66 fn assertions(&self) -> Vec<BrickAssertion> {
67 vec![
68 BrickAssertion::custom("littles_law_valid", |_| true),
69 BrickAssertion::max_latency_ms(1),
70 ]
71 }
72
73 fn budget(&self) -> BrickBudget {
74 BrickBudget {
75 collect_ms: 1,
76 layout_ms: 0,
77 render_ms: 0,
78 }
79 }
80
81 fn verify(&self) -> BrickVerification {
82 let mut v = BrickVerification::new();
83 for assertion in self.assertions() {
84 v.check(&assertion);
85 }
86 v
87 }
88
89 fn as_any(&self) -> &dyn Any {
90 self
91 }
92}