diff --git a/Cargo.toml b/Cargo.toml index ce0f01d4..1db2e895 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,8 +68,9 @@ derive_builder = "0.12.0" criterion = "0.5.0" jemalloc-ctl = "0.5.4" jemallocator = "0.5.4" -plotters = "0.3.5" -nalgebra = "0.29" +nalgebra = "0.32.3" +gnuplot = "0.0.39" + [[bench]] name = "dapol" diff --git a/benches/bench_data.csv b/benches/bench_data.csv new file mode 100644 index 00000000..cccd28ef --- /dev/null +++ b/benches/bench_data.csv @@ -0,0 +1,40 @@ +height/max_threads/num_users,compute_time(s),mem_usage(MB),file_size(MB) +16/4/10_000,0.8653,14.38,2.06 +16/4/20_000,0.8632,11.33,4.08 +16/4/30_000,0.7593,22.39,6.11 +16/8/10_000,0.864,6.05,2.06 +16/8/20_000,0.8624,11.97,4.08 +16/8/30_000,0.7859,21.34,6.11 +16/12/10_000,0.845,6.91,2.06 +16/12/20_000,0.8991,11.62,4.08 +16/12/30_000,0.7813,22.7,6.11 +16/16/10_000,0.862,5.9,2.06 +16/16/20_000,0.8523,12.38,4.08 +16/16/30_000,0.7837,21.57,6.11 +32/4/10_000,7.842,21.21,8.65 +32/4/20_000,15.314,42.03,12.55 +32/4/30_000,19.968,43.95,15.43 +32/4/50_000,33.424,57.9,20.1 +32/4/100_000,46.621,88.17,30.46 +32/4/200_000,73.565,176.35,50.69 +32/8/10_000,7.033,20.86,8.58 +32/8/20_000,11.796,42.22,12.55 +32/8/30_000,18.334,42.96,15.42 +32/8/50_000,28.259,58.42,20.11 +32/8/100_000,41.69,87.77,30.46 +32/8/200_000,70.453,176.28,50.69 +32/12/10_000,6.5743,20.84,8.63 +32/12/20_000,11.735,42.33,12.54 +32/12/30_000,17.593,43.86,15.41 +32/12/50_000,26.512,62.97,20.11 +32/12/100_000,40.098,88.59,30.46 +32/12/200_000,73.015,176.4,50.69 +32/16/10_000,6.3838,19.93,8.62 +32/16/20_000,11.938,43.17,12.55 +32/16/30_000,20.825,43.16,15.44 +32/16/50_000,31.582,59.2,20.11 +32/16/100_000,43.27,87.49,30.45 +32/16/200_000,71.469,176.5,50.69 +64/4/10_000,23.428,161.37,57.76 +64/4/20_000,45.441,321.9,109.24 +64/4/30_000,67.065,643.61,158.42 diff --git a/benches/dapol.rs b/benches/dapol.rs index 41d2fd3f..bb46ae62 100644 --- a/benches/dapol.rs +++ b/benches/dapol.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::path::PathBuf; use criterion::{criterion_group, criterion_main}; @@ -10,6 +11,7 @@ use dapol::{EntityId, Height, InclusionProof, MaxThreadCount}; mod heuristic_func; mod setup; + use crate::setup::{NUM_USERS, TREE_HEIGHTS}; #[global_allocator] @@ -297,8 +299,9 @@ fn bench_test_jemalloc_readings() { println!("Memory usage: {} allocated", setup::bytes_as_string(diff),); } -fn plot_plane() { - heuristic_func::plot(); +fn plot_plane() -> Result<(), Box> { + heuristic_func::plot()?; + Ok(()) } // ================================================================================================รท diff --git a/benches/heuristic_func.rs b/benches/heuristic_func.rs index d7aab0b1..18650cff 100644 --- a/benches/heuristic_func.rs +++ b/benches/heuristic_func.rs @@ -1,6 +1,13 @@ extern crate nalgebra as na; +use std::collections::HashMap; +use std::error::Error; +use std::fs::{File, OpenOptions}; use std::mem; +use std::path::PathBuf; + +use csv::ByteRecord; +use serde::Deserialize; use gnuplot::{ Figure, @@ -11,6 +18,56 @@ use na::{ArrayStorage, Const, Matrix}; // Assuming each hash value is 32 bytes (adjust based on your use case) const HASH_SIZE_BYTES: usize = 32; +type Data = HashMap; + +#[derive(Clone, Hash, Eq, PartialEq, Deserialize)] +struct Variable(String); + +#[derive(Deserialize)] +struct Metrics { + compute_time: f64, + mem_usage: f64, + file_size: f64, +} + +impl TryFrom<&Record> for Metrics { + type Error = &'static str; + + fn try_from(value: &Record) -> Result { + let compute_time = if let Some(c) = value.compute_time { + c + } else { + return Err("missing compute_time"); + }; + + let mem_usage = if let Some(m) = value.mem_usage { + m + } else { + return Err("missing mem_usage"); + }; + + let file_size = if let Some(f) = value.file_size { + f + } else { + return Err("missing file_size"); + }; + + Ok(Self { + compute_time, + mem_usage, + file_size, + }) + } +} + +#[derive(Clone, Deserialize)] +struct Record { + _variable: Variable, + compute_time: Option, + mem_usage: Option, + file_size: Option, +} + // Heuristic function to estimate memory usage for a Merkle Tree pub fn estimate_memory_usage(height: u8, num_users: u64) -> usize { // Calculate the number of hash values in the Merkle Tree @@ -23,22 +80,30 @@ pub fn estimate_memory_usage(height: u8, num_users: u64) -> usize { memory_usage_bytes } -pub fn plot() { - // TODO: replace with actual data (already collected) +pub fn plot() -> Result<(), Box> { // Define points - let points = vec![ - na::Point3::new(0.0, 0.0, 0.0), - na::Point3::new(1.0, 3.0, 5.0), - na::Point3::new(-5.0, 6.0, 3.0), - na::Point3::new(3.0, 6.0, 7.0), - na::Point3::new(-2.0, 6.0, 7.0), - ]; + // let points = vec![ + // na::Point3::new(0.0, 0.0, 0.0), + // na::Point3::new(1.0, 3.0, 5.0), + // na::Point3::new(-5.0, 6.0, 3.0), + // na::Point3::new(3.0, 6.0, 7.0), + // na::Point3::new(-2.0, 6.0, 7.0), + // ]; + + let data: Data = get_data(PathBuf::from("benches/bench_data.csv"))?; + let mut points: Vec> = Vec::new(); + + data.values().for_each(|m| { + points.push(na::Point3::new(m.compute_time, m.mem_usage, m.file_size)); + }); // Calculate best-fit plane let plane = fit_plane(&points); // Plot points and plane plot_3d(&points, plane); + + Ok(()) } fn fit_plane( @@ -90,3 +155,33 @@ fn plot_3d( // fg.save_to_png("benches/3d_plot.png", 640, 480) } + +// helper method +fn get_data(path: PathBuf) -> Result> { + let file: File = OpenOptions::new().read(true).open(path)?; // open summaries + + let mut rdr: csv::Reader = csv::ReaderBuilder::new() + .trim(csv::Trim::All) + .from_reader(file); + + let mut data: Data = HashMap::new(); + + let headers = ByteRecord::from(vec![ + "tree_height/max_threads/num_users", + "compute_time (s)", + "mem_usage (MB)", + "file_size (MB)", + ]); + + for result in rdr.byte_records() { + let byte_record: ByteRecord = result?; + let record: Record = byte_record.deserialize(Some(&headers))?; + + let variable: Variable = record.clone()._variable; + let metrics: Metrics = Metrics::try_from(&record)?; + + data.insert(variable, metrics); + } + + Ok(data) +} diff --git a/benches/setup.rs b/benches/setup.rs index 9ff0e76c..fface333 100644 --- a/benches/setup.rs +++ b/benches/setup.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::fs::{self}; use std::path::PathBuf; use dapol::accumulators::{NdmSmt, NdmSmtConfigBuilder};