use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use renacer::visualize::ring_buffer::HistoryBuffer;
fn generate_data(size: usize) -> Vec<f64> {
(0..size).map(|i| i as f64 * 0.5).collect()
}
fn bench_simd_stats(c: &mut Criterion) {
let mut group = c.benchmark_group("simd_vs_scalar_stats");
for size in [100, 300, 1000, 10_000] {
group.bench_with_input(BenchmarkId::new("simd_stats", size), &size, |b, &size| {
let mut buf = HistoryBuffer::new(size);
for v in generate_data(size) {
buf.push(v);
}
b.iter(|| {
black_box(buf.stats()) });
});
group.bench_with_input(BenchmarkId::new("scalar_stats", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
let sum: f64 = data.iter().sum();
let mean = sum / data.len() as f64;
let min = data.iter().copied().fold(f64::INFINITY, f64::min);
let max = data.iter().copied().fold(f64::NEG_INFINITY, f64::max);
black_box((min, max, mean))
});
});
}
group.finish();
}
fn bench_simd_sum(c: &mut Criterion) {
let mut group = c.benchmark_group("simd_vs_scalar_sum");
for size in [100, 300, 1000, 10_000] {
group.bench_with_input(BenchmarkId::new("simd_sum", size), &size, |b, &size| {
let mut buf = HistoryBuffer::new(size);
for v in generate_data(size) {
buf.push(v);
}
b.iter(|| {
black_box(buf.sum()) });
});
group.bench_with_input(BenchmarkId::new("scalar_sum", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
let sum: f64 = data.iter().sum();
black_box(sum)
});
});
}
group.finish();
}
fn bench_simd_minmax(c: &mut Criterion) {
let mut group = c.benchmark_group("simd_vs_scalar_minmax");
for size in [100, 300, 1000, 10_000] {
group.bench_with_input(BenchmarkId::new("simd_minmax", size), &size, |b, &size| {
let mut buf = HistoryBuffer::new(size);
for v in generate_data(size) {
buf.push(v);
}
b.iter(|| {
let min = buf.min();
let max = buf.max();
black_box((min, max))
});
});
group.bench_with_input(BenchmarkId::new("scalar_minmax", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
let min = data.iter().copied().fold(f64::INFINITY, f64::min);
let max = data.iter().copied().fold(f64::NEG_INFINITY, f64::max);
black_box((min, max))
});
});
}
group.finish();
}
fn bench_simd_normalize(c: &mut Criterion) {
use renacer::visualize::theme::normalize_batch;
let mut group = c.benchmark_group("simd_vs_scalar_normalize");
for size in [100, 300, 1000, 10_000] {
group.bench_with_input(BenchmarkId::new("simd_normalize", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
black_box(normalize_batch(&data)) });
});
group.bench_with_input(BenchmarkId::new("scalar_normalize", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
let max = data.iter().copied().fold(f64::NEG_INFINITY, f64::max);
let normalized: Vec<f64> = if max == 0.0 {
vec![0.0; data.len()]
} else {
data.iter().map(|v| v / max).collect()
};
black_box(normalized)
});
});
}
group.finish();
}
fn bench_simd_sparkline(c: &mut Criterion) {
use renacer::visualize::theme::sparkline;
let mut group = c.benchmark_group("simd_vs_scalar_sparkline");
for size in [50, 100, 300] {
group.bench_with_input(BenchmarkId::new("simd_sparkline", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
black_box(sparkline(&data, size)) });
});
group.bench_with_input(BenchmarkId::new("scalar_sparkline", size), &size, |b, &size| {
let data = generate_data(size);
b.iter(|| {
let min = data.iter().copied().fold(f64::INFINITY, f64::min);
let max = data.iter().copied().fold(f64::NEG_INFINITY, f64::max);
let range = max - min;
let spark: String = data
.iter()
.take(size)
.map(|v| {
if range == 0.0 || v.is_nan() {
'▁'
} else {
let normalized = ((v - min) / range).clamp(0.0, 1.0);
let idx = (normalized * 7.0).round() as usize;
['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'][idx.min(7)]
}
})
.collect();
black_box(spark)
});
});
}
group.finish();
}
criterion_group!(
benches,
bench_simd_stats,
bench_simd_sum,
bench_simd_minmax,
bench_simd_normalize,
bench_simd_sparkline,
);
criterion_main!(benches);