From 186de671604660945f94d212287e3141396f31fb Mon Sep 17 00:00:00 2001 From: Alec Smrekar Date: Fri, 22 Dec 2023 11:26:49 +0100 Subject: [PATCH 1/3] Issue 429: Implement ItemsPerSecond --- src/graph.rs | 76 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index 1c443223..b9ae989f 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -15,12 +15,47 @@ use std::collections::HashMap; use std::fmt::Write; use std::marker::PhantomData; +#[derive(Clone)] +struct ItemsPerSecond(HashMap>); + +impl ItemsPerSecond { + fn new() -> ItemsPerSecond { + ItemsPerSecond(Default::default()) + } + + fn initialize_or_increment(&mut self, key: &str, second: usize, value: u32) -> u32 { + if !self.0.contains_key(key) { + self.0.insert(key.to_string(), TimeSeries::new()); + } + let data = self.0.get_mut(key).unwrap(); + data.increase_value(second, value); + data.get(second) + } + + #[allow(dead_code)] + fn insert(&mut self, key: &str, time_series: TimeSeries) { + self.0.insert(key.to_string(), time_series); + } + + fn len(&self) -> usize { + self.0.len() + } + + fn get(&self, key: &str) -> Option> { + self.0.get(key).cloned() + } + + fn get_map(&self) -> HashMap> { + self.0.clone() + } +} + /// Used to collect graph data during a load test. pub(crate) struct GraphData { /// Counts requests per second for each request type. - requests_per_second: HashMap>, + requests_per_second: ItemsPerSecond, /// Counts errors per second. - errors_per_second: HashMap>, + errors_per_second: ItemsPerSecond, /// Maintains average response time per second. average_response_time_per_second: HashMap>, /// Number of transactions at the end of each second of the test. @@ -36,8 +71,8 @@ impl GraphData { pub(crate) fn new() -> Self { trace!("new graph"); GraphData { - requests_per_second: HashMap::new(), - errors_per_second: HashMap::new(), + requests_per_second: ItemsPerSecond::new(), + errors_per_second: ItemsPerSecond::new(), average_response_time_per_second: HashMap::new(), transactions_per_second: TimeSeries::new(), scenarios_per_second: TimeSeries::new(), @@ -47,33 +82,24 @@ impl GraphData { /// Record requests per second metric. pub(crate) fn record_requests_per_second(&mut self, key: &str, second: usize) { - if !self.requests_per_second.contains_key(key) { - self.requests_per_second - .insert(key.to_string(), TimeSeries::new()); - } - let data = self.requests_per_second.get_mut(key).unwrap(); - data.increase_value(second, 1); - + let value = self + .requests_per_second + .initialize_or_increment(key, second, 1); debug!( "incremented second {} for requests per second counter: {}", - second, - data.get(second) + second, value ); } /// Record errors per second metric. pub(crate) fn record_errors_per_second(&mut self, key: &str, second: usize) { - if !self.errors_per_second.contains_key(key) { - self.errors_per_second - .insert(key.to_string(), TimeSeries::new()); - } - let data = self.errors_per_second.get_mut(key).unwrap(); - data.increase_value(second, 1); + let value = self + .errors_per_second + .initialize_or_increment(key, second, 1); debug!( "incremented second {} for errors per second counter: {}", - second, - data.get(second) + second, value ); } @@ -141,7 +167,7 @@ impl GraphData { "graph-rps", "Requests #", granular_data, - self.requests_per_second.clone(), + self.requests_per_second.get_map(), ) } @@ -190,7 +216,7 @@ impl GraphData { "graph-eps", "Errors #", granular_data, - self.errors_per_second.clone(), + self.errors_per_second.get_map(), ) } @@ -807,7 +833,7 @@ mod test { fn test_graph_setters() { let mut graph = GraphData::new(); graph.requests_per_second.insert( - "GET /".to_string(), + "GET /", TimeSeries { data: vec![123, 234, 345, 456, 567], phantom: PhantomData, @@ -864,7 +890,7 @@ mod test { }; graph.errors_per_second.insert( - "GET /".to_string(), + "GET /", TimeSeries { data: vec![567, 123, 234, 345, 456], phantom: PhantomData, From 3ccbbbcfeb7583b1c97613daa49130aac369257b Mon Sep 17 00:00:00 2001 From: Alec Smrekar Date: Wed, 10 Jan 2024 18:38:01 +0100 Subject: [PATCH 2/3] Issue 429: Optimize ItemsPerSecond based on PR feedback --- src/graph.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index b9ae989f..eef38652 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -23,28 +23,40 @@ impl ItemsPerSecond { ItemsPerSecond(Default::default()) } + #[inline(always)] fn initialize_or_increment(&mut self, key: &str, second: usize, value: u32) -> u32 { - if !self.0.contains_key(key) { - self.0.insert(key.to_string(), TimeSeries::new()); + if !self.contains_key(key) { + self.insert(key, TimeSeries::new()); } let data = self.0.get_mut(key).unwrap(); data.increase_value(second, value); data.get(second) } + #[inline(always)] + fn contains_key(&mut self, key: &str) -> bool { + self.0.contains_key(key) + } + + #[inline(always)] #[allow(dead_code)] fn insert(&mut self, key: &str, time_series: TimeSeries) { self.0.insert(key.to_string(), time_series); } + #[inline(always)] + #[allow(dead_code)] fn len(&self) -> usize { self.0.len() } + #[inline(always)] + #[allow(dead_code)] fn get(&self, key: &str) -> Option> { self.0.get(key).cloned() } + #[inline(always)] fn get_map(&self) -> HashMap> { self.0.clone() } From 40d3977cb2c69613a25b0efd48804b42b616d86c Mon Sep 17 00:00:00 2001 From: Alec Smrekar Date: Mon, 15 Jan 2024 08:04:16 +0100 Subject: [PATCH 3/3] Issue 429: Remove deadcode rule --- src/graph.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graph.rs b/src/graph.rs index eef38652..8548e3c0 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -39,7 +39,6 @@ impl ItemsPerSecond { } #[inline(always)] - #[allow(dead_code)] fn insert(&mut self, key: &str, time_series: TimeSeries) { self.0.insert(key.to_string(), time_series); }