use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
use std::fs::File;
use std::io::{Read, Write};
use tempfile::NamedTempFile;
use timber_rs::accelerated::SimdLiteralMatcher;
use timber_rs::analyzer::{LiteralMatcher, PatternMatcher};
fn create_benchmark_log(size: usize, pattern_frequency: usize) -> NamedTempFile {
let temp_file = NamedTempFile::new().unwrap();
let mut file = File::create(temp_file.path()).unwrap();
for i in 0..size {
let level = match i % 5 {
0 => "ERROR",
1 => "WARN",
2 => "INFO",
3 => "DEBUG",
_ => "TRACE",
};
let message = if i % pattern_frequency == 0 {
"Exception occurred in process_data"
} else {
"Normal log message"
};
writeln!(
file,
"2025-03-21 {:02}:{:02}:00,{:03} [{}] {}",
(i / 60) % 24,
i % 60,
i % 1000,
level,
message
)
.unwrap();
}
temp_file
}
fn bench_pattern_matching(c: &mut Criterion) {
let mut group = c.benchmark_group("pattern_matching");
let log_file = create_benchmark_log(10_000, 100);
let mut file = File::open(log_file.path()).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
let patterns = [
"Exception", "process_data", "Normal log message", "NonExistentPattern", ];
for pattern in &patterns {
group.bench_with_input(
BenchmarkId::new("standard", pattern),
pattern,
|b, pattern| {
let matcher = LiteralMatcher::new(pattern);
b.iter(|| {
let mut matches = 0;
for line in content.lines() {
if matcher.is_match(black_box(line)) {
matches += 1;
}
}
black_box(matches)
});
},
);
}
for pattern in &patterns {
group.bench_with_input(BenchmarkId::new("simd", pattern), pattern, |b, pattern| {
let matcher = SimdLiteralMatcher::new(pattern);
b.iter(|| {
let mut matches = 0;
for line in content.lines() {
if matcher.is_match(black_box(line)) {
matches += 1;
}
}
black_box(matches)
});
});
}
group.finish();
}
fn bench_pattern_matching_large(c: &mut Criterion) {
let mut group = c.benchmark_group("pattern_matching_large");
group.sample_size(10);
let log_file = create_benchmark_log(100_000, 500);
let mut file = File::open(log_file.path()).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
let patterns = [
"Exception", ];
for pattern in &patterns {
group.bench_with_input(
BenchmarkId::new("standard_large", pattern),
pattern,
|b, pattern| {
let matcher = LiteralMatcher::new(pattern);
b.iter(|| {
let mut matches = 0;
for line in content.lines() {
if matcher.is_match(black_box(line)) {
matches += 1;
}
}
black_box(matches)
});
},
);
group.bench_with_input(
BenchmarkId::new("simd_large", pattern),
pattern,
|b, pattern| {
let matcher = SimdLiteralMatcher::new(pattern);
b.iter(|| {
let mut matches = 0;
for line in content.lines() {
if matcher.is_match(black_box(line)) {
matches += 1;
}
}
black_box(matches)
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_pattern_matching,
bench_pattern_matching_large
);
criterion_main!(benches);