use criterion::{criterion_group, criterion_main, Criterion}; use rand::{ distributions::{Alphanumeric, DistString}, thread_rng, Rng, }; use cover::library::{Artist, Library, Song}; // actual benchmarks fn bench_random_library(c: &mut Criterion) { bench_random_library_with_sizes(c, "small", 5, 25); bench_random_library_with_sizes(c, "medium", 25, 100); bench_random_library_with_sizes(c, "large", 100, 1000); bench_random_library_with_sizes(c, "massive", 1000, 2500); } // benchmark helpers fn bench_random_library_with_sizes(c: &mut Criterion, size: &str, artists: usize, songs: usize) { let id = format!("{size} random library ({artists} artists x {songs} songs/artist)"); let library = random_library(artists, songs); c.bench_function(id.as_str(), |b| { b.iter(|| { library.library_covers(); }) }); } // test data generators fn random_string() -> String { let mut rng = thread_rng(); let length = rng.gen_range(1..=20); Alphanumeric.sample_string(&mut rng, length) } fn generate_iter(generator: impl Fn() -> T, length: usize) -> impl Iterator { let mut ts = Vec::with_capacity(length); for _ in 0..length { ts.push(generator()) } ts.into_iter() } fn random_song() -> Song { Song::new( random_string(), random_string(), generate_iter(random_string, 5), ) } fn random_artist(songs: usize) -> Artist { Artist::new( random_string(), generate_iter(random_string, 5), generate_iter(random_song, songs), ) } fn random_library(artists: usize, songs_per_artist: usize) -> Library { Library::new(generate_iter(|| random_artist(songs_per_artist), artists)) } // entrypoint criterion_group!(benches, bench_random_library); criterion_main!(benches);