Skip to main content

streaming_crypto/core_api/benchmarks/
bench_results.rs

1use std::collections::HashMap;
2use std::time::Instant;
3use serde::Serialize;
4
5use crate::benchmarks::bench_utils::{measure_cpu_percent, measure_memory_mb, get_timestamp};
6
7#[derive(Debug, Clone, Serialize)]
8pub struct BenchmarkResult {
9    pub mode: String,
10    pub op: String,
11    pub size: usize,
12    pub compression: String,
13    pub chunk_size: usize,
14    pub elapsed: f64,
15    pub mb_per_s: f64,
16    pub ratio: Option<f64>,
17    pub cpu_percent: f64,
18    pub mem_before: f64,
19    pub mem_after: f64,
20    pub timestamp: String,
21    pub scenario: Option<String>,
22    pub traces: Option<HashMap<String, String>>,
23}
24
25impl BenchmarkResult {
26    pub fn pretty_row(&self) -> String {
27        let mb = self.size as f64 / 1e6;
28        let ratio_str = match self.ratio {
29            Some(r) => format!("{:.3}", r),
30            None => "-".to_string(),
31        };
32        format!(
33            "{:5} | {:8} | {:8.2} MB | {:7}  | {:6.0} KB | {:8.2} ms | {:8.2} MB/s | {:7} | {:6.1}% | {:6.1} → {:6.1} MB",
34            self.mode,
35            self.op,
36            mb,
37            self.compression,
38            self.chunk_size as f64 / 1024.0,
39            self.elapsed * 1000.0,
40            self.mb_per_s,
41            ratio_str,
42            self.cpu_percent,
43            self.mem_before,
44            self.mem_after
45        )
46    }
47}
48
49pub fn pretty_row_header() -> String {
50    format!(
51        "mode  | op       | size MB     | compress | ch_size   | elapsed     | MB/s          | ratio   |  CPU%   | RSS (MB)"
52    )
53}
54
55pub fn print_results(results: &[BenchmarkResult], title: &str) {
56    let len_line = 125;
57    println!("\n{}", "=".repeat(len_line));
58    println!("{}", title);
59    println!("{}", "=".repeat(len_line));
60
61    println!("{}", pretty_row_header());
62    println!("{}", "-".repeat(len_line));
63
64    let mut current_scenario: Option<String> = None;
65
66    let mut sorted_results = results.to_vec();
67    sorted_results.sort_by(|a, b| a.scenario.cmp(&b.scenario));
68
69    for r in sorted_results {
70        if current_scenario != r.scenario {
71            if current_scenario.is_some() {
72                println!("{}", "-".repeat(len_line));
73            }
74            current_scenario = r.scenario.clone();
75            if let Some(s) = &current_scenario {
76                println!("{}", s);
77                println!("{}", "-".repeat(len_line));
78            }
79        }
80        println!("{}", r.pretty_row());
81    }
82
83    println!("{}", "=".repeat(len_line));
84}
85
86/// Rust equivalent of Python's make_result_v2
87pub fn make_result_v2(
88    scenario: &str,
89    op: &str,
90    mode: &str,
91    size: usize,
92    compression: &str,
93    chunk_size: usize,
94    start: Instant,
95    mem_before: f64,
96    total_ct: Option<usize>,
97    traces: Option<HashMap<String, String>>,
98) -> BenchmarkResult {
99    let elapsed = start.elapsed().as_secs_f64();
100    let cpu_percent = measure_cpu_percent(elapsed);
101    let mem_after = measure_memory_mb();
102
103    let mut mbps = 0.0;
104    let mut ratio = None;
105
106    if size > 0 {
107        mbps = size as f64 / elapsed / 1e6;
108        if let Some(ct) = total_ct {
109            // ✅ ratio is only meaningful during encryption
110            if compression != "none" && op == "encrypt" {
111                ratio = Some(ct as f64 / size as f64);
112            }
113        }
114    }
115
116    BenchmarkResult {
117        scenario: Some(scenario.to_string()),
118        op: op.to_string(),
119        mode: mode.to_string(),
120        size,
121        compression: compression.to_string(),
122        chunk_size,
123        elapsed,
124        mb_per_s: mbps,
125        ratio,
126        cpu_percent,
127        mem_before,
128        mem_after,
129        timestamp: get_timestamp(),
130        traces,
131    }
132}
133
134// ### 🧩 Key Notes
135// - **Elapsed time**: Uses `Instant` to measure duration (`start.elapsed().as_secs_f64()`).
136// - **Throughput (MB/s)**: `size / elapsed / 1e6`.
137// - **Ratio**: Only set during encryption and when compression is not `"none"`.
138// - **Scenario & traces**: Optional fields, consistent with our struct.
139// - **Helpers**: `measure_cpu_percent`, `measure_memory_mb`, and `get_timestamp` are placeholders — we’ll plug in our real implementations.