ruvector_profiler/
latency.rs1#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
2pub struct LatencyRecord {
3 pub sample_id: usize,
4 pub wall_time_us: u64,
5 pub kernel_time_us: u64,
6 pub seq_len: usize,
7}
8
9#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
10pub struct LatencyStats {
11 pub p50_us: u64,
12 pub p95_us: u64,
13 pub p99_us: u64,
14 pub mean_us: f64,
15 pub std_us: f64,
16 pub n: usize,
17}
18
19pub fn compute_latency_stats(records: &[LatencyRecord]) -> LatencyStats {
21 let n = records.len();
22 if n == 0 {
23 return LatencyStats {
24 p50_us: 0,
25 p95_us: 0,
26 p99_us: 0,
27 mean_us: 0.0,
28 std_us: 0.0,
29 n: 0,
30 };
31 }
32 let mut times: Vec<u64> = records.iter().map(|r| r.wall_time_us).collect();
33 times.sort_unstable();
34 let mean = times.iter().sum::<u64>() as f64 / n as f64;
35 let var = times
36 .iter()
37 .map(|&t| (t as f64 - mean).powi(2))
38 .sum::<f64>()
39 / n as f64;
40 LatencyStats {
41 p50_us: pctl(×, 50.0),
42 p95_us: pctl(×, 95.0),
43 p99_us: pctl(×, 99.0),
44 mean_us: mean,
45 std_us: var.sqrt(),
46 n,
47 }
48}
49
50fn pctl(sorted: &[u64], p: f64) -> u64 {
51 let idx = ((p / 100.0 * sorted.len() as f64).ceil() as usize)
52 .min(sorted.len())
53 .saturating_sub(1);
54 sorted[idx]
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 fn recs(ts: &[u64]) -> Vec<LatencyRecord> {
61 ts.iter()
62 .enumerate()
63 .map(|(i, &t)| LatencyRecord {
64 sample_id: i,
65 wall_time_us: t,
66 kernel_time_us: t,
67 seq_len: 128,
68 })
69 .collect()
70 }
71
72 #[test]
73 fn empty() {
74 assert_eq!(compute_latency_stats(&[]).n, 0);
75 }
76 #[test]
77 fn single() {
78 let s = compute_latency_stats(&recs(&[42]));
79 assert_eq!((s.p50_us, s.p99_us, s.n), (42, 42, 1));
80 }
81 #[test]
82 fn multi() {
83 let s = compute_latency_stats(&recs(&[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]));
84 assert_eq!(s.p50_us, 50);
85 assert!((s.mean_us - 55.0).abs() < 1e-9);
86 }
87 #[test]
88 fn unsorted() {
89 assert_eq!(
90 compute_latency_stats(&recs(&[100, 10, 50, 90, 20])).p50_us,
91 50
92 );
93 }
94}