Skip to main content

ruvector_profiler/
csv_emitter.rs

1use crate::latency::LatencyRecord;
2use crate::memory::MemorySnapshot;
3use std::io::Write;
4
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
6pub struct ResultRow {
7    pub setting: String,
8    pub coherence_delta: f64,
9    pub kv_cache_reduction: f64,
10    pub peak_mem_reduction: f64,
11    pub energy_reduction: f64,
12    pub p95_latency_us: u64,
13    pub accuracy: f64,
14}
15
16pub fn write_results_csv(path: &str, rows: &[ResultRow]) -> std::io::Result<()> {
17    let mut f = std::fs::File::create(path)?;
18    writeln!(f, "setting,coherence_delta,kv_cache_reduction,peak_mem_reduction,energy_reduction,p95_latency_us,accuracy")?;
19    for r in rows {
20        writeln!(
21            f,
22            "{},{},{},{},{},{},{}",
23            esc(&r.setting),
24            r.coherence_delta,
25            r.kv_cache_reduction,
26            r.peak_mem_reduction,
27            r.energy_reduction,
28            r.p95_latency_us,
29            r.accuracy
30        )?;
31    }
32    Ok(())
33}
34
35pub fn write_latency_csv(path: &str, records: &[LatencyRecord]) -> std::io::Result<()> {
36    let mut f = std::fs::File::create(path)?;
37    writeln!(f, "sample_id,wall_time_us,kernel_time_us,seq_len")?;
38    for r in records {
39        writeln!(
40            f,
41            "{},{},{},{}",
42            r.sample_id, r.wall_time_us, r.kernel_time_us, r.seq_len
43        )?;
44    }
45    Ok(())
46}
47
48pub fn write_memory_csv(path: &str, snapshots: &[MemorySnapshot]) -> std::io::Result<()> {
49    let mut f = std::fs::File::create(path)?;
50    writeln!(
51        f,
52        "timestamp_us,peak_rss_bytes,kv_cache_bytes,activation_bytes,temp_buffer_bytes"
53    )?;
54    for s in snapshots {
55        writeln!(
56            f,
57            "{},{},{},{},{}",
58            s.timestamp_us,
59            s.peak_rss_bytes,
60            s.kv_cache_bytes,
61            s.activation_bytes,
62            s.temp_buffer_bytes
63        )?;
64    }
65    Ok(())
66}
67
68fn esc(s: &str) -> String {
69    if s.contains(',') || s.contains('"') || s.contains('\n') {
70        format!("\"{}\"", s.replace('"', "\"\""))
71    } else {
72        s.to_string()
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn esc_plain() {
82        assert_eq!(esc("hello"), "hello");
83    }
84    #[test]
85    fn esc_comma() {
86        assert_eq!(esc("a,b"), "\"a,b\"");
87    }
88
89    #[test]
90    fn roundtrip_results() {
91        let d = tempfile::tempdir().unwrap();
92        let p = d.path().join("r.csv");
93        write_results_csv(
94            p.to_str().unwrap(),
95            &[ResultRow {
96                setting: "base".into(),
97                coherence_delta: 0.01,
98                kv_cache_reduction: 0.0,
99                peak_mem_reduction: 0.0,
100                energy_reduction: 0.0,
101                p95_latency_us: 1200,
102                accuracy: 0.95,
103            }],
104        )
105        .unwrap();
106        let c = std::fs::read_to_string(&p).unwrap();
107        assert_eq!(c.lines().count(), 2);
108    }
109
110    #[test]
111    fn roundtrip_latency() {
112        let d = tempfile::tempdir().unwrap();
113        let p = d.path().join("l.csv");
114        write_latency_csv(
115            p.to_str().unwrap(),
116            &[LatencyRecord {
117                sample_id: 0,
118                wall_time_us: 100,
119                kernel_time_us: 80,
120                seq_len: 64,
121            }],
122        )
123        .unwrap();
124        assert_eq!(std::fs::read_to_string(&p).unwrap().lines().count(), 2);
125    }
126
127    #[test]
128    fn roundtrip_memory() {
129        let d = tempfile::tempdir().unwrap();
130        let p = d.path().join("m.csv");
131        write_memory_csv(
132            p.to_str().unwrap(),
133            &[MemorySnapshot {
134                peak_rss_bytes: 1024,
135                kv_cache_bytes: 256,
136                activation_bytes: 512,
137                temp_buffer_bytes: 128,
138                timestamp_us: 999,
139            }],
140        )
141        .unwrap();
142        let c = std::fs::read_to_string(&p).unwrap();
143        assert!(c.contains("999,1024,256,512,128"));
144    }
145}