LTS data collection was occasionally overflowing on calculating

the mean average. If a large-enough block had to be summed,
the total could overflow the storage type. To prevent this from
ever happening, we instead calculate the median - which is
likely to give a better representation anyway.

Also fixes a compile warning.
This commit is contained in:
Herbert Wolverson
2023-11-13 08:18:26 -06:00
parent 0169ab836e
commit d3e2884273
2 changed files with 17 additions and 6 deletions

View File

@@ -78,7 +78,7 @@ impl UnixSocketServer {
}
fn make_socket_public() -> Result<(), UnixSocketServerError> {
lqos_utils::run_success!(
let _ = lqos_utils::run_success!(
"/bin/chmod",
"-R",
"a+rwx",

View File

@@ -7,6 +7,21 @@ pub(crate) struct MinMaxAvg<T> {
pub(crate) avg: T,
}
fn median<T>(stats: &[T]) -> T
where
T: Bounded + Zero + std::ops::AddAssign<T> + Copy + std::cmp::Ord + CheckedDiv + NumCast,
{
let mut sorted = stats.to_vec();
sorted.sort();
let len = sorted.len();
let mid = len / 2;
if len % 2 == 0 {
(sorted[mid] + sorted[mid - 1]).checked_div(&T::from(2).unwrap()).unwrap_or(T::zero())
} else {
sorted[mid]
}
}
impl<
T: Bounded
+ Zero
@@ -20,17 +35,13 @@ impl<
pub(crate) fn from_slice(stats: &[T]) -> Self {
let mut min = T::max_value();
let mut max = T::min_value();
let mut avg = T::zero();
stats.iter().for_each(|n| {
avg += *n;
min = T::min(min, *n);
max = T::max(max, *n);
});
let len = T::from(stats.len()).unwrap();
avg = avg.checked_div(&len).unwrap_or(T::zero());
Self { max, min, avg }
Self { max, min, avg: median(stats) }
}
}