use criterion::{criterion_group, criterion_main, Criterion, BatchSize};
use std::time::{Duration, Instant};
use rayon::prelude::*;
use parallel_task::prelude::*;
use rand::Rng;
#[derive(Debug, Clone)]
struct Job {
duration: Duration,
}
impl Job {
fn run(&self) {
let start = Instant::now();
while start.elapsed() < self.duration {
std::hint::spin_loop();
}
}
}
fn create_micro_jobs(count: usize) -> Vec<Job> {
let mut rng = rand::rng();
(0..count)
.map(|_| {
let p = rng.random_range(0..100);
let micros = if p < 90 {
rng.random_range(50..=500)
} else {
rng.random_range(500..=1000)
};
Job {
duration: Duration::from_micros(micros),
}
})
.collect()
}
fn bench_micro_jobs(c: &mut Criterion) {
let job_count = 10_00;
let base_jobs = create_micro_jobs(job_count);
c.bench_function("Normal (owned)", |b| {
b.iter_batched(
|| base_jobs.clone(), |jobs| {
jobs.into_iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
c.bench_function("Rayon (owned)", |b| {
b.iter_batched(
|| base_jobs.clone(),
|jobs| {
jobs.into_par_iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
c.bench_function("PT (owned)", |b| {
b.iter_batched(
|| base_jobs.clone(),
|jobs| {
jobs.into_parallel_iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
c.bench_function("Normal (&iter)", |b| {
b.iter_batched_ref(
|| base_jobs.clone(),
|jobs| {
jobs.iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
c.bench_function("Rayon (&iter)", |b| {
b.iter_batched_ref(
|| base_jobs.clone(),
|jobs| {
jobs.par_iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
c.bench_function("PT (&iter)", |b| {
b.iter_batched_ref(
|| base_jobs.clone(),
|jobs| {
jobs.parallel_iter().for_each(|j| j.run());
},
BatchSize::SmallInput,
);
});
}
criterion_group!(benches, bench_micro_jobs);
criterion_main!(benches);