1use std::{
4 fmt::Display,
5 fs::{read_to_string, File},
6 io::{self, Write},
7 path::Path,
8};
9
10use crate::bencher::DEFAULT_RUNS;
11use plotly::{Histogram, Plot};
12
13pub fn import_csv(file: impl AsRef<Path>) -> io::Result<Vec<(String, Vec<u128>)>> {
19 let lines = read_to_string(file)?; if lines.trim().is_empty() {
21 return Ok(vec![]);
23 }
24 let no_lines = lines.lines().count(); let lines = lines.lines();
26
27 let mut trace_contents: Vec<(String, Vec<u128>)> = Vec::with_capacity(no_lines);
28 for line in lines {
29 let mut title = String::new();
30 let mut contents = Vec::with_capacity(
31 trace_contents
32 .first()
33 .map_or(DEFAULT_RUNS, |(_, v)| v.len()),
34 ); for (j, time) in line.split(',').enumerate() {
36 if j == 0 {
37 title = time.to_string(); } else {
39 contents.push(time.parse().expect("unable to parse time")); }
41 }
42 trace_contents.push((title, contents));
43 }
44
45 Ok(trace_contents)
46}
47
48pub fn get_traces(
53 trace_file_names: impl IntoIterator<Item = impl AsRef<Path>>,
54 trace: Option<(String, Vec<u128>)>,
55) -> io::Result<Vec<(String, Vec<u128>)>> {
56 let mut traces: Vec<(String, Vec<u128>)> = trace_file_names
57 .into_iter() .map(import_csv) .collect::<io::Result<Vec<Vec<(String, Vec<u128>)>>>>()? .into_iter() .flatten() .collect(); if let Some((name, times)) = trace {
64 traces.push((name, times)); }
67 Ok(traces)
68}
69
70pub fn export_csv(
76 trace: Option<(String, Vec<u128>)>,
77 file_name_input: impl AsRef<Path> + Display,
78 extra_trace_file_names: impl IntoIterator<Item = impl AsRef<Path>>,
79) -> io::Result<usize> {
80 let traces = get_traces(extra_trace_file_names, trace)?; export_csv_no_file_input(file_name_input, traces) }
83
84pub fn export_csv_no_file_input(
90 file_name_input: impl AsRef<Path> + Display,
91 traces: Vec<(String, Vec<u128>)>,
92) -> io::Result<usize> {
93 let mut to_be_written = String::new(); for (name, times) in traces {
96 to_be_written += &name;
97 for time in times {
98 to_be_written += ",";
99 to_be_written += &time.to_string();
100 }
101 to_be_written += "\n";
102 } let mut file = File::create(format!("{file_name_input}.csv"))?; let to_be_written = to_be_written.as_bytes(); file.write_all(to_be_written)?; Ok(to_be_written.len())
109}
110
111pub fn export_html(
117 trace: Option<(String, Vec<u128>)>,
118 file_name_input: impl AsRef<Path> + Display,
119 extra_trace_file_names: impl IntoIterator<Item = impl AsRef<Path>>,
120) -> io::Result<usize> {
121 let traces = get_traces(extra_trace_file_names, trace)?; export_html_no_file_input(file_name_input, traces) }
124
125pub fn export_html_no_file_input(
131 file_name_input: impl AsRef<Path> + Display,
132 traces: Vec<(String, Vec<u128>)>,
133) -> io::Result<usize> {
134 let mut plot = Plot::new(); for (name, trace) in traces {
136 plot.add_trace(Histogram::new(trace).name(name)); }
138
139 let mut file = File::create(format!("{file_name_input}.html"))?; let html = plot.to_html(); let html = html.as_bytes(); file.write_all(html)?; Ok(html.len())
145}