use std::path::Path;
use std::io::prelude::Write;
use std::io::BufWriter;
use crate::pellapsedtime::PEllapsedTime;
pub struct PFunctionTimer{
p_function_name: String,
p_nb_measure: usize,
p_nb_call_per_measure: usize,
p_vec_nb_element: Vec<usize>,
p_vec_time: Vec<PEllapsedTime>,
}
impl PFunctionTimer{
pub fn new(nb_measure: usize, nb_call_per_measure: usize, vec_nb_element: &Vec<usize>) -> Self{
PFunctionTimer{
p_function_name: String::from(""),
p_nb_measure: nb_measure,
p_nb_call_per_measure: nb_call_per_measure,
p_vec_nb_element: vec_nb_element.clone(),
p_vec_time: vec![]
}
}
pub fn set_function_name(&mut self, function_name: &String){
self.p_function_name = function_name.to_owned();
}
pub fn add_time_perf(&mut self, time_perf: &PEllapsedTime){
self.p_vec_time.push(time_perf.clone());
}
pub fn get_nb_measure(&self) -> usize{
self.p_nb_measure
}
pub fn get_function_name(&self) -> &String{
&self.p_function_name
}
pub fn get_nb_call_per_measure(&self) -> usize{
self.p_nb_call_per_measure
}
pub fn get_vec_nb_element(&self) -> &Vec<usize> {
&self.p_vec_nb_element
}
pub fn eval_perf(&mut self, call_timer_eval_function: &dyn Fn(&mut Self, usize)){
for nb_element in self.p_vec_nb_element.clone().iter(){
call_timer_eval_function(self, nb_element.clone());
}
}
pub fn save_gnuplot(&self, filename: &Path) -> std::io::Result<()> {
let mut file = BufWriter::new(std::fs::File::create(filename).unwrap());
file.write(&format!("# PFunctionTimer : save performance of function '{}'\n", self.p_function_name).into_bytes())?;
file.write(&format!("# nb_element\tmin_time[ns]\tfirst_quartile_time[ns]\tmedian_time[ns]\tlast_quartile_time[ns]\tmax_time[ns]\n").into_bytes())?;
for perf in self.p_vec_time.iter() {
file.write(&format!("{:12}\t{:12}\t{:23}\t{:15}\t{:22}\t{:12}\n", perf.get_nb_element(),
perf.get_min_ellapsed_time_ns(),
perf.get_first_quartile_ellapsed_time_ns(),
perf.get_median_ellapsed_time_ns(),
perf.get_last_quartile_ellapsed_time_ns(),
perf.get_max_ellapsed_time_ns()
).into_bytes())?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use std::path::PathBuf;
use crate::phoenix_function_timer;
fn hadamard_product(vec_res: &mut Vec<f32>, vec_x: &Vec<f32>, vec_y: &Vec<f32>){
*vec_res = vec_x.into_iter().zip(vec_y)
.map(|(x, y)| x * y)
.collect::<Vec<_>>();
}
fn timer_hadamard_product(function_timer: &mut PFunctionTimer, nb_element: usize){
let vec_x: Vec<f32> = vec![1.0; nb_element];
let vec_y: Vec<f32> = vec![2.0; nb_element];
let mut vec_res: Vec<f32> = vec![0.0; nb_element];
phoenix_function_timer!(function_timer, nb_element, hadamard_product(&mut vec_res, &vec_x, &vec_y));
}
#[test]
fn test_pfunction_timer(){
let mut function_timer: PFunctionTimer = PFunctionTimer::new(100, 10, &vec![1000, 1500, 2000, 2500, 3000, 4000, 5000]);
function_timer.eval_perf(&timer_hadamard_product);
fs::create_dir_all("generated").unwrap();
function_timer.save_gnuplot(&PathBuf::from("generated/hadamard_product_perf.txt")).unwrap();
assert_eq!(function_timer.get_function_name().to_owned(), String::from("hadamard_product"));
}
}