use std::hint::black_box;
use std::io::Cursor;
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;
fn synthetic_ept(target_bytes: usize) -> String {
let mut s = String::with_capacity(target_bytes + 2048);
let mut i = 0usize;
while s.len() < target_bytes {
s.push_str("// <( BEGIN WORD )>\n");
for j in 0..31 {
s.push_str(&format!(
"host line {i}-{j}: lorem ipsum dolor sit amet, consectetur adipiscing elit\n"
));
}
s.push_str("// <( END WORD )>\n");
i += 1;
}
s
}
fn main() {
let sizes_mb: Vec<usize> = std::env::args()
.skip(1)
.filter_map(|a| a.parse().ok())
.collect();
let sizes_mb = if sizes_mb.is_empty() {
vec![10]
} else {
sizes_mb
};
let _profiler = dhat::Profiler::builder().build();
for mb in sizes_mb {
let input = synthetic_ept(mb * 1_000_000);
let peak_before = dhat::HeapStats::get().max_bytes;
let mut paops =
enprot::etree::ParseOps::new(Box::new(enprot::crypto::CryptoPolicyDefault {}))
.expect("ParseOps");
paops.transforms.encrypt.insert("WORD".to_string());
paops
.passwords
.insert("WORD".to_string(), "bench-password".to_string());
paops.crypto.pbkdfopts.msec = Some(1);
let tree = enprot::etree::parse(Cursor::new(input.as_bytes()), &mut paops).expect("parse");
let tree = enprot::etree::transform(&tree, &mut paops).expect("transform");
let mut out = Vec::new();
enprot::etree::tree_write(&mut out, &tree, &mut paops).expect("write");
black_box(&out);
let stats = dhat::HeapStats::get();
let peak = stats.max_bytes - peak_before;
println!(
"input {:>4} MB → output {:>4} MB | peak heap this phase: {:>6.1} MB | process high-water: {:>6.1} MB",
mb,
out.len() as f64 / 1_000_000.0,
peak as f64 / 1_000_000.0,
stats.max_bytes as f64 / 1_000_000.0,
);
}
}