benches/end_to_end_bench.rs

//! End-to-end benchmark: generate log lines, filter, render to a buffer.
//!
//! Gives a single "lines per second" number that captures the full pipeline.

use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};

use ripgrab::filter::{dsl, FilterSet, MatchOutcome};
use ripgrab::render::mode::stream::StreamRenderer;

mod fixtures;

fn bench_end_to_end(c: &mut Criterion) {
    let lines = fixtures::access_log(fixtures::DEFAULT_LINES);
    let filter = FilterSet::compile(&[], &[], None).unwrap();
    let compiled = dsl::parse_and_compile("status >= 400").unwrap();

    let mut group = c.benchmark_group("pipeline");
    group.throughput(Throughput::Elements(lines.len() as u64));
    group.bench_function("end-to-end", |b| {
        b.iter(|| {
            let mut buf = Vec::with_capacity(lines.iter().map(|l| l.len() + 1).sum());
            let mut renderer = StreamRenderer::new(&mut buf, true, false);
            let mut ctx = dsl::EvalContext::new();
            for line in &lines {
                ctx.clear();
                ctx.set("status", extract_status(line));
                if !dsl::evaluate(&compiled, &ctx) {
                    continue;
                }
                if let MatchOutcome::Plain = filter.apply(line) {
                    renderer.render("bench.log", black_box(line)).unwrap();
                }
            }
            black_box(buf)
        });
    });
    group.finish();
}

fn extract_status(line: &str) -> &str {
    line.split_whitespace()
        .find_map(|f| f.strip_prefix("status="))
        .unwrap_or("0")
}

criterion_group!(benches, bench_end_to_end);
criterion_main!(benches);