use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use std::time::Duration;
fn generate_normal_data(n: usize, seed: u64) -> Vec<f64> {
let mut state = seed;
let mut data = Vec::with_capacity(n);
for _ in 0..n {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u1 = (state >> 33) as f64 / (1u64 << 31) as f64;
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let u2 = (state >> 33) as f64 / (1u64 << 31) as f64;
let z = (-2.0 * u1.max(1e-10).ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
data.push(z);
}
data
}
fn generate_xy_data(n: usize, seed: u64) -> (Vec<f64>, Vec<f64>) {
let mut state = seed;
let mut x = Vec::with_capacity(n);
let mut y = Vec::with_capacity(n);
for i in 0..n {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let noise = ((state >> 33) as f64 / (1u64 << 31) as f64 - 0.5) * 0.1;
x.push(i as f64 + noise);
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let y_noise = ((state >> 33) as f64 / (1u64 << 31) as f64 - 0.5) * 0.5;
y.push((i as f64 * 0.1).sin() + y_noise);
}
(x, y)
}
fn generate_grid_data(nx: usize, ny: usize, seed: u64) -> (Vec<f64>, Vec<f64>, Vec<Vec<f64>>) {
let mut state = seed;
let x: Vec<f64> = (0..nx)
.map(|i| i as f64 / (nx - 1) as f64 * 10.0 - 5.0)
.collect();
let y: Vec<f64> = (0..ny)
.map(|i| i as f64 / (ny - 1) as f64 * 10.0 - 5.0)
.collect();
let mut z = Vec::with_capacity(ny);
for &yj in y.iter().take(ny) {
let mut row = Vec::with_capacity(nx);
for &xi in x.iter().take(nx) {
let base = (-0.1 * (xi * xi + yj * yj)).exp();
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let noise = ((state >> 33) as f64 / (1u64 << 31) as f64 - 0.5) * 0.05;
row.push(base + noise);
}
z.push(row);
}
(x, y, z)
}
#[allow(dead_code)]
fn generate_categorical_data(n: usize, seed: u64) -> (Vec<String>, Vec<f64>) {
let mut state = seed;
let categories: Vec<String> = (0..n).map(|i| format!("Category {}", i)).collect();
let values: Vec<f64> = (0..n)
.map(|_| {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
(state >> 33) as f64 / (1u64 << 31) as f64 * 100.0
})
.collect();
(categories, values)
}
fn bench_kde(c: &mut Criterion) {
let mut group = c.benchmark_group("kde");
group.measurement_time(Duration::from_secs(10));
let sizes = [1_000, 10_000, 100_000];
for &size in &sizes {
let data = generate_normal_data(size, 12345);
group.throughput(Throughput::Elements(size as u64));
group.bench_with_input(BenchmarkId::new("compute", size), &data, |b, data| {
b.iter(|| {
let sum: f64 = black_box(data).iter().sum();
black_box(sum)
})
});
}
group.finish();
}
fn bench_ecdf(c: &mut Criterion) {
let mut group = c.benchmark_group("ecdf");
group.measurement_time(Duration::from_secs(10));
let sizes = [1_000, 10_000, 100_000];
for &size in &sizes {
let data = generate_normal_data(size, 54321);
group.throughput(Throughput::Elements(size as u64));
group.bench_with_input(BenchmarkId::new("compute", size), &data, |b, data| {
b.iter(|| {
let mut sorted = black_box(data).clone();
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
black_box(sorted)
})
});
}
group.finish();
}
fn bench_step(c: &mut Criterion) {
let mut group = c.benchmark_group("step");
group.measurement_time(Duration::from_secs(10));
let sizes = [1_000, 10_000, 100_000];
for &size in &sizes {
let (x, y) = generate_xy_data(size, 11111);
group.throughput(Throughput::Elements(size as u64));
group.bench_with_input(BenchmarkId::new("compute", size), &(&x, &y), |b, (x, y)| {
b.iter(|| {
let mut step_x = Vec::with_capacity(x.len() * 2);
let mut step_y = Vec::with_capacity(y.len() * 2);
for i in 0..x.len() {
if i > 0 {
step_x.push(black_box(x)[i]);
step_y.push(black_box(y)[i - 1]);
}
step_x.push(x[i]);
step_y.push(y[i]);
}
black_box((step_x, step_y))
})
});
}
group.finish();
}
fn bench_contour(c: &mut Criterion) {
let mut group = c.benchmark_group("contour");
group.measurement_time(Duration::from_secs(10));
let grid_sizes = [50, 100, 200];
for &size in &grid_sizes {
let (_x, _y, z) = generate_grid_data(size, size, 99999);
group.throughput(Throughput::Elements((size * size) as u64));
group.bench_with_input(BenchmarkId::new("grid_gen", size), &size, |b, &size| {
b.iter(|| {
let (_x, _y, z) = generate_grid_data(black_box(size), size, 99999);
black_box(z)
})
});
group.bench_with_input(BenchmarkId::new("data_access", size), &z, |b, z| {
b.iter(|| {
let sum: f64 = black_box(z).iter().flat_map(|row| row.iter()).sum();
black_box(sum)
})
});
}
group.finish();
}
fn bench_plot_area(c: &mut Criterion) {
use ruviz::prelude::PlotArea;
let mut group = c.benchmark_group("plot_area");
let area = PlotArea::new(100.0, 50.0, 600.0, 400.0, 0.0, 10.0, 0.0, 100.0);
group.bench_function("data_to_screen", |b| {
b.iter(|| area.data_to_screen(black_box(5.0), black_box(50.0)))
});
group.bench_function("screen_to_data", |b| {
b.iter(|| area.screen_to_data(black_box(400.0), black_box(250.0)))
});
group.bench_function("contains_data", |b| {
b.iter(|| area.contains_data(black_box(5.0), black_box(50.0)))
});
let n = 10_000;
let data_points: Vec<(f64, f64)> = (0..n)
.map(|i| (i as f64 / 1000.0, i as f64 / 100.0))
.collect();
group.throughput(Throughput::Elements(n as u64));
group.bench_with_input(
BenchmarkId::new("batch_transform", n),
&data_points,
|b, points| {
b.iter(|| {
let screen_points: Vec<(f32, f32)> = black_box(points)
.iter()
.map(|&(x, y)| area.data_to_screen(x, y))
.collect();
black_box(screen_points)
})
},
);
group.finish();
}
fn bench_plot_builder(c: &mut Criterion) {
use ruviz::prelude::*;
let mut group = c.benchmark_group("plot_builder");
group.bench_function("method_chain", |b| {
b.iter(|| {
let plot = Plot::new()
.title("Test Plot")
.xlabel("X Axis")
.ylabel("Y Axis")
.size(8.0, 6.0)
.dpi(100);
black_box(plot)
})
});
group.finish();
}
criterion_group!(distribution_benches, bench_kde, bench_ecdf,);
criterion_group!(discrete_benches, bench_step,);
criterion_group!(continuous_benches, bench_contour,);
criterion_group!(infrastructure_benches, bench_plot_area, bench_plot_builder,);
criterion_main!(
distribution_benches,
discrete_benches,
continuous_benches,
infrastructure_benches,
);