#![allow(clippy::expect_used)]
#![allow(clippy::panic)]
use criterion::{Criterion, Throughput, criterion_group, criterion_main};
use rand::{Rng, thread_rng};
use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use std::{
collections::HashSet,
fs::File,
io::Write,
path::{Path, PathBuf},
process::{Command, exit},
time::Duration,
};
use tempfile::tempdir;
const SAMPLE_SIZE: usize = 20;
const DEFAULT_WALLET_PRIVATE_KEY: &str =
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
fn autonomi_file_upload(dir: &str) -> String {
let autonomi_cli_path = get_cli_path();
let output = Command::new(autonomi_cli_path)
.arg("--local")
.arg("file")
.arg("upload")
.arg(dir)
.output()
.expect("Failed to execute command");
if !output.status.success() {
let err = output.stderr;
let err_string = String::from_utf8(err).expect("Failed to parse error string");
panic!("Upload command executed with failing error code: {err_string:?}");
} else {
let out = output.stdout;
let out_string = String::from_utf8(out).expect("Failed to parse output string");
println!("upload output is :\n{out_string:?}");
println!("All lines in output:");
for (i, line) in out_string.lines().enumerate() {
println!("Line {i}: {line:?}");
if line.contains("At address:") {
println!("Found line with 'At address:' at index {i}");
}
}
let address = out_string
.lines()
.find(|line| line.contains("At address:"))
.expect("Failed to find the address of the uploaded file");
let address = address
.split("At address:")
.nth(1)
.expect("Failed to extract address from line")
.trim();
let address_str = address.to_string();
println!("Parsed address is: {address_str:?}");
address_str
}
}
fn autonomi_file_download(uploaded_files: HashSet<String>) {
let autonomi_cli_path = get_cli_path();
let temp_dir = tempdir().expect("Failed to create temp dest dir");
for address in uploaded_files.iter() {
let dest_file = temp_dir.path().join(address);
println!("Trying to download {address:?} to as the dest_file of {dest_file:?}");
let output = Command::new(autonomi_cli_path.clone())
.arg("--local")
.arg("file")
.arg("download")
.arg("--disable-cache")
.arg(address)
.arg(dest_file)
.output()
.expect("Failed to execute command");
if !output.status.success() {
let err = output.stderr;
let err_string = String::from_utf8(err).expect("Failed to parse error string");
panic!("Download command executed with failing error code: {err_string:?}");
}
}
}
fn generate_file(path: &PathBuf, file_size_mb: usize) {
let mut file = File::create(path).expect("Failed to create file");
let mut rng = thread_rng();
let n_small_chunks = file_size_mb * 1024 * 32;
for _ in 0..n_small_chunks {
let random_data: [u8; 32] = rng.r#gen();
file.write_all(&random_data)
.expect("Failed to write to file");
}
let size = file.metadata().expect("Failed to get metadata").len() as f64 / (1024 * 1024) as f64;
assert_eq!(file_size_mb as f64, size);
}
fn get_cli_path() -> PathBuf {
let mut path = PathBuf::new();
if let Ok(val) = std::env::var("CARGO_TARGET_DIR") {
path.push(val);
} else {
path.push("target");
}
path.push("release");
path.push("ant");
path
}
fn criterion_benchmark(c: &mut Criterion) {
let cli_path = get_cli_path();
if !Path::new(&cli_path).exists() {
eprintln!(
"Error: Binary {cli_path:?} does not exist. Please make sure to compile your project first"
);
exit(1);
}
if std::env::var("SECRET_KEY").is_err() {
#[allow(unsafe_code)]
unsafe {
std::env::set_var("SECRET_KEY", DEFAULT_WALLET_PRIVATE_KEY);
}
}
let sizes: [u64; 2] = [1, 10]; let mut total_uploaded_files = HashSet::new();
let mut total_size: u64 = 0;
for size in sizes.iter() {
let temp_dir = tempdir().expect("Failed to create temp dir");
let temp_dir_path = temp_dir.keep();
let mut uploaded_files = HashSet::new();
let file_paths: Vec<PathBuf> = (0..50)
.into_par_iter()
.map(|idx| {
let path = temp_dir_path.join(format!("random_file_{size}_mb_{idx}"));
generate_file(&path, *size as usize);
path
})
.collect();
std::thread::sleep(Duration::from_secs(10));
let mut group = c.benchmark_group(format!("Upload Benchmark {size}MB"));
group.sampling_mode(criterion::SamplingMode::Flat);
group.measurement_time(Duration::from_secs(5));
group.warm_up_time(Duration::from_secs(5));
group.sample_size(SAMPLE_SIZE);
let mut file_path_iter = file_paths.iter();
group.throughput(Throughput::Bytes(size * 1024 * 1024));
let bench_id = format!("ant files upload {size}mb");
group.bench_function(bench_id, |b| {
b.iter(|| {
let file_path = file_path_iter.next().expect("Temp files drained up.");
let uploaded_address = autonomi_file_upload(
file_path
.to_str()
.expect("Invalid temp file path encountered"),
);
uploaded_files.insert(uploaded_address);
})
});
group.finish();
println!(
"Got total {} files uploaded after iteration of {size} data_size.",
uploaded_files.len()
);
total_size += size * (uploaded_files.len() as u64 + 2);
total_uploaded_files.extend(uploaded_files);
}
let mut group = c.benchmark_group("Download Benchmark".to_string());
group.sampling_mode(criterion::SamplingMode::Flat);
group.measurement_time(Duration::from_secs(10));
group.warm_up_time(Duration::from_secs(5));
group.sample_size(SAMPLE_SIZE / 2);
group.throughput(Throughput::Bytes(total_size * 1024 * 1024));
let bench_id = "ant files download".to_string();
group.bench_function(bench_id, |b| {
b.iter(|| autonomi_file_download(total_uploaded_files.clone()))
});
group.finish();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);