Add week 8 materials

This commit is contained in:
osukhoroslov committed 2026-11-04 19:23:39 +03:00
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);
}
}