Add week 8 materials
This commit is contained in:
1 parent
a987b82834
commit
0bf71ed374
38 files changed
+2908
No files matched your search
@@ -0,0 +1,132 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub const WINDOW: f64 = 60.0;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
struct RequestTime {
|
||||
time: f64,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl Eq for RequestTime {}
|
||||
|
||||
impl Ord for RequestTime {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.time
|
||||
.total_cmp(&other.time)
|
||||
.then(self.id.cmp(&other.id))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for RequestTime {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
/// Nearest-rank p99 of response times for requests arriving in [t, t + WINDOW).
|
||||
/// Emit one point per distinct arrival time t <= time_limit.
|
||||
pub fn windowed_p99(mut requests: Vec<(f64, f64)>, time_limit: f64) -> Vec<(f64, f64)> {
|
||||
requests.sort_by(|a, b| a.0.total_cmp(&b.0));
|
||||
let mut result = Vec::new();
|
||||
let mut items = BTreeSet::new();
|
||||
let mut end = 0;
|
||||
let mut start = 0;
|
||||
while start < requests.len() && requests[start].0 <= time_limit {
|
||||
let time = requests[start].0;
|
||||
while end < requests.len() && requests[end].0 < time + WINDOW {
|
||||
items.insert(RequestTime {
|
||||
time: requests[end].1,
|
||||
id: end,
|
||||
});
|
||||
end += 1;
|
||||
}
|
||||
// ceil(0.99 * n), computed exactly, without floating-point rounding.
|
||||
let rank = items.len() - items.len() / 100;
|
||||
let p99 = items.iter().rev().nth(items.len() - rank).unwrap().time;
|
||||
result.push((time, p99));
|
||||
// Equal response times remain distinct observations thanks to id.
|
||||
// Remove the entire arrival-time group before advancing the window.
|
||||
while start < requests.len() && requests[start].0 == time {
|
||||
items.remove(&RequestTime {
|
||||
time: requests[start].1,
|
||||
id: start,
|
||||
});
|
||||
start += 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn expires_old_requests_and_excludes_right_boundary() {
|
||||
let requests = vec![
|
||||
(0.0, 100.0),
|
||||
(1.0, 10.0),
|
||||
(61.0, 1.0),
|
||||
(62.0, 1.0),
|
||||
(123.0, 3.0),
|
||||
];
|
||||
assert_eq!(
|
||||
windowed_p99(requests, 123.0),
|
||||
vec![
|
||||
(0.0, 100.0),
|
||||
(1.0, 10.0),
|
||||
(61.0, 1.0),
|
||||
(62.0, 1.0),
|
||||
(123.0, 3.0)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uses_nearest_rank_and_counts_equal_response_times() {
|
||||
let mut requests = vec![(0.0, 1.0); 99];
|
||||
requests.push((0.0, 100.0));
|
||||
assert_eq!(windowed_p99(requests, 0.0), vec![(0.0, 1.0)]);
|
||||
let requests = (1..=100).map(|n| (0.0, n as f64)).collect();
|
||||
assert_eq!(windowed_p99(requests, 0.0), vec![(0.0, 99.0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sorts_arrivals_and_limits_reported_times() {
|
||||
assert_eq!(
|
||||
windowed_p99(vec![(120.0, 8.0), (60.0, 2.0), (0.0, 4.0)], 60.0),
|
||||
vec![(0.0, 4.0), (60.0, 2.0)]
|
||||
);
|
||||
assert!(windowed_p99(Vec::new(), 60.0).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_independent_sort_per_window_reference() {
|
||||
let requests: Vec<_> = (0..400)
|
||||
.map(|i| (((i * 37) % 241) as f64, ((i * 17) % 31 + 1) as f64))
|
||||
.collect();
|
||||
let mut times: Vec<_> = requests
|
||||
.iter()
|
||||
.map(|r| r.0)
|
||||
.filter(|t| *t <= 180.0)
|
||||
.collect();
|
||||
times.sort_by(f64::total_cmp);
|
||||
times.dedup();
|
||||
let expected: Vec<_> = times
|
||||
.into_iter()
|
||||
.map(|t| {
|
||||
let mut values: Vec<_> = requests
|
||||
.iter()
|
||||
.filter(|r| r.0 >= t && r.0 < t + WINDOW)
|
||||
.map(|r| r.1)
|
||||
.collect();
|
||||
values.sort_by(f64::total_cmp);
|
||||
let rank = (0.99 * values.len() as f64).ceil() as usize;
|
||||
(t, values[rank - 1])
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(windowed_p99(requests, 180.0), expected);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user