use std::hint::black_box;
use synta::types::SequenceOf;
use synta::{Decoder, Encoder, Encoding};
use synta::{Element, Integer};
fn parse_with_element(data: &[u8]) -> Result<usize, Box<dyn std::error::Error>> {
let mut decoder = Decoder::new(data, Encoding::Der);
let elem = decoder.decode::<Element>()?;
let count = match elem {
Element::Sequence(seq) => seq.iter().count(),
_ => 0,
};
Ok(count)
}
fn parse_with_sequenceof(data: &[u8]) -> Result<usize, Box<dyn std::error::Error>> {
let mut decoder = Decoder::new(data, Encoding::Der);
let seq = decoder.decode::<SequenceOf<Integer>>()?;
let count = seq.count();
Ok(count)
}
fn parse_with_sequenceof_collect(data: &[u8]) -> Result<usize, Box<dyn std::error::Error>> {
let mut decoder = Decoder::new(data, Encoding::Der);
let seq = decoder.decode::<SequenceOf<Integer>>()?;
let vec = seq.collect_vec()?;
Ok(vec.len())
}
fn create_test_data(num_elements: usize) -> Vec<u8> {
let elements: Vec<Integer> = (0..num_elements).map(|i| Integer::from(i as i64)).collect();
let seq = SequenceOf::from_vec(elements).expect("Failed to create SequenceOf");
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&seq).expect("Failed to encode");
encoder.finish().expect("Failed to finish encoding")
}
fn run_benchmark(
name: &str,
data: &[u8],
iterations: usize,
parse_fn: impl Fn(&[u8]) -> Result<usize, Box<dyn std::error::Error>>,
) -> std::time::Duration {
let start = std::time::Instant::now();
for _ in 0..iterations {
let _ = black_box(parse_fn(black_box(data)));
}
let elapsed = start.elapsed();
let per_iter = elapsed / iterations as u32;
println!(" {:<30} {:>12?} ({:>10?} total)", name, per_iter, elapsed);
elapsed
}
fn main() {
println!("SequenceOf vs Element Benchmark\n");
println!("This compares lazy SequenceOf iteration vs eager Element parsing");
println!("for SEQUENCE OF Integer structures.\n");
const ITERATIONS: usize = 100_000;
let test_sizes = vec![5, 10, 20, 50];
for size in test_sizes {
println!("=== Test: SEQUENCE OF with {} Integer elements ===", size);
let data = create_test_data(size);
println!("Encoded size: {} bytes", data.len());
println!("Running {} iterations per method:\n", ITERATIONS);
let element_time =
run_benchmark("Element (eager Vec)", &data, ITERATIONS, parse_with_element);
let sequenceof_time = run_benchmark(
"SequenceOf (lazy iteration)",
&data,
ITERATIONS,
parse_with_sequenceof,
);
let sequenceof_collect_time = run_benchmark(
"SequenceOf + collect_vec",
&data,
ITERATIONS,
parse_with_sequenceof_collect,
);
let lazy_improvement = ((element_time.as_nanos() as f64
- sequenceof_time.as_nanos() as f64)
/ element_time.as_nanos() as f64)
* 100.0;
let collect_improvement = ((element_time.as_nanos() as f64
- sequenceof_collect_time.as_nanos() as f64)
/ element_time.as_nanos() as f64)
* 100.0;
println!("\n Results:");
println!(
" Lazy iteration: {:>6.1}% {} than Element",
lazy_improvement.abs(),
if lazy_improvement > 0.0 {
"faster"
} else {
"slower"
}
);
println!(
" With collect: {:>6.1}% {} than Element",
collect_improvement.abs(),
if collect_improvement > 0.0 {
"faster"
} else {
"slower"
}
);
println!();
}
println!("\n=== Summary ===");
println!("SequenceOf lazy iteration shows the performance benefit when:");
println!(" - You iterate once without collecting");
println!(" - You only need some elements (early termination)");
println!(" - You want zero allocation on parse");
println!("\nElement is better when:");
println!(" - You need random access to elements");
println!(" - You iterate multiple times");
println!(" - Element size is very small");
}