use rand::distributions::{Distribution, Uniform}; use std::{path::Path}; use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use path_no_alloc::with_paths; pub fn array_from_idx(f: impl FnMut(usize) -> T) -> [T; N] { let mut indices = [0; N]; for i in 0..N { indices[i] = i; } indices.map(f) } pub fn criterion_benchmark(c: &mut Criterion) { let p1 = "Call me Ishmael. Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore"; let p2 = "I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation."; let p1_slices = array_from_idx::<129, _>(|i| &p1[..i]); let p2_slices = array_from_idx::<129, _>(|i| &p2[..i]); let mut group = c.benchmark_group("Path join"); for i in 1..128 { group.bench_with_input(BenchmarkId::new("with_paths!", i), &i, |b, i| { b.iter(|| { let p1 = p1_slices[*i]; let p2 = p2_slices[*i]; with_paths! { path = p1 / p2 => black_box(path) }; }) }); group.bench_with_input(BenchmarkId::new("Path.join", i), &i, |b, i| { b.iter(|| { let p1 = p1_slices[*i]; let p2 = p2_slices[*i]; black_box(Path::new(p1).join(p2)) }) }); } } pub fn join_random(c: &mut Criterion) { let mut rng = rand::thread_rng(); const SAMPLE_SIZE: usize = 1 << 17; let options = b"abcdef/"; let opt_dist = Uniform::from(0..options.len()); let mut group = c.benchmark_group("join"); for mean_len in (1..12).map(|i| i * 10) { let length_dist = Uniform::from(0..mean_len); let mut paths: Vec = vec![]; paths.reserve(SAMPLE_SIZE); for _ in 0..SAMPLE_SIZE { let len = length_dist.sample(&mut rng); let s: String = opt_dist .sample_iter(&mut rng) .take(len) .map(|i| options[i] as char) .collect(); paths.push(s); } let mut i1 = 0; let mut i2 = 0; group.bench_function(BenchmarkId::new("with_paths!", mean_len), |b| { b.iter(|| { let p1 = &paths[i1]; let p2 = &paths[i2]; with_paths! { path = p1 / p2 => black_box(path) }; i1 = (i1 + 1) % SAMPLE_SIZE; i2 = (i2 + 2) % SAMPLE_SIZE; }) }); i1 = 0; i2 = 0; group.bench_function(BenchmarkId::new("Path.join", mean_len), |b| { b.iter(|| { let p1 = &paths[i1]; let p2 = &paths[i2]; black_box(Path::new(p1).join(p2)); i1 = (i1 + 1) % SAMPLE_SIZE; i2 = (i2 + 2) % SAMPLE_SIZE; }) }); } } pub fn exists_random(c: &mut Criterion) { let mut rng = rand::thread_rng(); const SAMPLE_SIZE: usize = 1 << 17; let options = b"abcdef/"; let opt_dist = Uniform::from(0..options.len()); let mut group = c.benchmark_group("exists"); for mean_len in (1..12).map(|i| i * 10) { let length_dist = Uniform::from(0..mean_len); let mut paths: Vec = vec![]; paths.reserve(SAMPLE_SIZE); for _ in 0..SAMPLE_SIZE { let len = length_dist.sample(&mut rng); let s: String = opt_dist .sample_iter(&mut rng) .take(len) .map(|i| options[i] as char) .collect(); paths.push(s); } let mut i1 = 0; let mut i2 = 0; group.bench_function(BenchmarkId::new("with_paths!", mean_len), |b| { b.iter(|| { let p1 = &paths[i1]; let p2 = &paths[i2]; with_paths! { path = p1 / p2 => black_box(path.exists()) }; i1 = (i1 + 1) % SAMPLE_SIZE; i2 = (i2 + 2) % SAMPLE_SIZE; }) }); i1 = 0; i2 = 0; group.bench_function(BenchmarkId::new("Path.join", mean_len), |b| { b.iter(|| { let p1 = &paths[i1]; let p2 = &paths[i2]; black_box(Path::new(p1).join(p2).exists()); i1 = (i1 + 1) % SAMPLE_SIZE; i2 = (i2 + 2) % SAMPLE_SIZE; }) }); } } criterion_group!(benches, criterion_benchmark); criterion_group!(random, join_random, exists_random); criterion_main!(benches, random);