1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use std::collections::BTreeMap;

use run::{RequestResult, Seconds};

#[derive(Debug, Serialize)]
pub struct TimeSeries(Vec<Item>);
impl TimeSeries {
    pub fn new(results: Vec<RequestResult>) -> Self {
        let mut items = BTreeMap::new();
        let mut latencies = BTreeMap::new();
        for r in results {
            let time = r.start_time().0 as usize;
            let item = items.entry(time).or_insert_with(|| Item {
                time,
                ..Item::default()
            });
            item.requests += 1;

            latencies
                .entry(time)
                .or_insert_with(Vec::new)
                .push(r.elapsed().0);
        }
        TimeSeries(
            items
                .into_iter()
                .map(|(time, mut item)| {
                    let latencies = latencies.get_mut(&time).unwrap();
                    latencies.sort_by_key(|l| Seconds(*l));
                    item.latency.min = latencies[0];
                    item.latency.median = latencies[latencies.len() / 2];
                    item.latency.mean = latencies.iter().sum::<f64>() / latencies.len() as f64;
                    item.latency.max = *latencies.last().unwrap();
                    item
                })
                .collect(),
        )
    }
}

#[derive(Debug, Default, Serialize)]
pub struct Item {
    pub time: usize, // seconds
    pub requests: usize,
    pub latency: Latency,
}

#[derive(Debug, Default, Serialize)]
pub struct Latency {
    pub min: f64,
    pub mean: f64,
    pub median: f64,
    pub max: f64,
}