use bindet::{detect, detect_at_start, FileTypeMatches}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rand::Rng; use std::fs::{read_dir, OpenOptions}; use std::io::{BufReader, BufWriter, Error, Write}; use std::path::{Path, PathBuf}; fn generate>(path: P, size: usize) { if path.as_ref().exists() { return; } let mut file = OpenOptions::new() .write(true) .create(true) .open(path) .expect("failed to write random data"); let mut writer = BufWriter::new(&mut file); let mut rng = rand::thread_rng(); let mut buffer = [0u8; 8096]; let mut total = 0; while total < size { let write_size = std::cmp::min(size - total, buffer.len()); let buffer = &mut buffer[..write_size]; rng.fill(buffer); writer.write(buffer).expect("failed to write random data"); total += write_size; } } fn list_files() -> impl Iterator { read_dir("files/") .expect("failed to read files directory") .map(|entry| entry.expect("failed to read entry").path()) .filter(|p| { p.extension().map_or(false, |e| { e.to_str().map_or(false, |s| s != "big" && s != "asc") }) }) } fn test_detect

(path: P) -> Result, Error> where P: AsRef, { let file = OpenOptions::new().read(true).open(path).unwrap(); let buf = BufReader::new(file); detect(buf) } fn test_fast_detect

(path: P) -> Result, Error> where P: AsRef, { let file = OpenOptions::new().read(true).open(path).unwrap(); let buf = BufReader::new(file); detect_at_start(buf) } fn detect_rar_sfx() -> Result, Error> { test_detect(black_box("files/hello-world.exe")) } fn detect_2mib_sfx() -> Result, Error> { test_detect(black_box("files/2mib.exe")) } fn detect_fast_2mib_sfx() -> Result, Error> { test_fast_detect(black_box("files/2mib.exe")) } fn detect_fast_rar_sfx() -> Result, Error> { test_fast_detect(black_box("files/hello-world.exe")) } fn criterion_benchmark(c: &mut Criterion) { { let mut group = c.benchmark_group("sfx"); group.bench_function("sfx", |b| b.iter(detect_rar_sfx)); group.bench_function("start-of-sfx", |b| b.iter(detect_fast_rar_sfx)); group.bench_function("2mib-sfx", |b| b.iter(detect_2mib_sfx)); group.bench_function("start-of-2mib-sfx", |b| b.iter(detect_fast_2mib_sfx)); generate("files/1gib.data.big", 1 << 30); generate("files/100mib.data.big", 100 << 20); group.bench_function("1gib", |b| { b.iter(|| test_detect(black_box("files/1gib.data.big"))) }); group.bench_function("start-of-1gib", |b| { b.iter(|| test_fast_detect(black_box("files/1gib.data.big"))) }); group.bench_function("100mib", |b| { b.iter(|| test_detect(black_box("files/100mib.data.big"))) }); group.bench_function("start-of-100mib", |b| { b.iter(|| test_fast_detect(black_box("files/100mib.data.big"))) }); } { let mut group = c.benchmark_group("regular_detections"); group.bench_function("little_tar", |b| { b.iter(|| test_detect(black_box("files/test.tar"))) }); group.bench_function("1mb_tar", |b| { b.iter(|| test_detect(black_box("files/test-0.tar"))) }); group.bench_function("multi", |b| { b.iter(|| { let _ = black_box(test_detect(black_box("files/hello.rar"))); let _ = black_box(test_detect(black_box("files/hello.zip"))); let _ = black_box(test_detect(black_box("files/rust-logo.png"))); }) }); } { let mut group = c.benchmark_group("all-types"); let mut files = list_files(); for file in files { let name = file.file_stem().expect("name").to_str().expect("name"); let ext = file .extension() .expect("extension") .to_str() .expect("extension"); group.bench_with_input(format!("{name}-{ext}"), &file, |b, file| { b.iter(|| test_detect(file)) }); } } } criterion_group! { name = benches; config = Criterion::default().sample_size(50); targets = criterion_benchmark } criterion_main!(benches);