tidaldb/tidal/benches/text_index.rs
jx12n 3bcfb3c576 feat: Bazel build, crate docs/ai-lookup, docker images, and engine hardening
- Add BUILD.bazel across tidal, tidal-net, tidal-server, tidalctl for bzlmod build
- Add tidal/ crate docs (README, CHANGELOG, CONTRIBUTING, AGENTS, CLAUDE, API, ARCHITECTURE) and ai-lookup reference
- Add docker standalone/cluster/deploy images, compose, and prometheus config
- Harden WAL (batch format, writer, dedup, diagnostics), text syncer/collectors, and vector registry
- Expand tidalctl CLI and tests; restructure WAL/visibility integration test suites
- Refine tidal-net transport/client/server and tidal-server cluster/scatter-gather
2026-06-07 18:29:38 -06:00

138 lines
4.1 KiB
Rust

#![allow(clippy::unwrap_used)]
//! Criterion benchmarks for the BM25 text index pipeline.
//!
//! Measures BM25 query latency at various corpus sizes to validate the
//! < 10ms target at 10K documents specified in the m5p1 phase acceptance criteria.
use std::collections::HashMap;
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use tidaldb::{
schema::{EntityId, TextFieldDef, TextFieldType},
text::{AllScoresCollector, TextIndex},
};
fn make_index(n: u64) -> TextIndex {
let fields = vec![
TextFieldDef {
key: "title".into(),
field_type: TextFieldType::Text,
},
TextFieldDef {
key: "description".into(),
field_type: TextFieldType::Text,
},
TextFieldDef {
key: "category".into(),
field_type: TextFieldType::Keyword,
},
];
let idx = TextIndex::ephemeral(&fields).unwrap();
let mut w = idx.writer_guard().unwrap();
for i in 0..n {
let mut meta = HashMap::new();
// Vary titles so BM25 IDF scoring is meaningful.
meta.insert(
"title".into(),
format!("Rust tutorial {i} async concurrency"),
);
meta.insert(
"description".into(),
"Learn Rust programming with practical examples and real projects.".into(),
);
// Alternate categories to test keyword field throughput.
let cat = if i % 2 == 0 { "programming" } else { "systems" };
meta.insert("category".into(), cat.into());
w.index_item(EntityId::new(i), &meta).unwrap();
}
w.commit(n).unwrap();
drop(w);
idx.reload_reader().unwrap();
idx
}
/// BM25 bare-term query at 1K docs.
fn bench_bm25_1k(c: &mut Criterion) {
let idx = make_index(1_000);
let searcher = idx.searcher();
let parser = idx.query_parser();
let collector = AllScoresCollector {
entity_id_field: idx.fields().entity_id,
};
c.bench_function("bm25_query_1k_docs", |b| {
b.iter(|| {
let q = parser.parse(black_box("Rust async")).unwrap();
let results = searcher.search(q.as_ref(), &collector).unwrap();
black_box(results)
});
});
}
/// BM25 bare-term query at 10K docs — must complete in < 10ms.
fn bench_bm25_10k(c: &mut Criterion) {
let idx = make_index(10_000);
let searcher = idx.searcher();
let parser = idx.query_parser();
let collector = AllScoresCollector {
entity_id_field: idx.fields().entity_id,
};
c.bench_function("bm25_query_10k_docs", |b| {
b.iter(|| {
let q = parser.parse(black_box("Rust async")).unwrap();
let results = searcher.search(q.as_ref(), &collector).unwrap();
black_box(results)
});
});
}
/// BM25 exact-phrase query at 10K docs.
fn bench_bm25_phrase_10k(c: &mut Criterion) {
let idx = make_index(10_000);
let searcher = idx.searcher();
let parser = idx.query_parser();
let collector = AllScoresCollector {
entity_id_field: idx.fields().entity_id,
};
c.bench_function("bm25_phrase_10k_docs", |b| {
b.iter(|| {
let q = parser.parse(black_box("\"Rust programming\"")).unwrap();
let results = searcher.search(q.as_ref(), &collector).unwrap();
black_box(results)
});
});
}
/// BM25 keyword field-scoped query at 10K docs.
fn bench_bm25_keyword_10k(c: &mut Criterion) {
let idx = make_index(10_000);
let searcher = idx.searcher();
let parser = idx.query_parser();
let collector = AllScoresCollector {
entity_id_field: idx.fields().entity_id,
};
c.bench_function("bm25_keyword_10k_docs", |b| {
b.iter(|| {
let q = parser.parse(black_box("category:programming")).unwrap();
let results = searcher.search(q.as_ref(), &collector).unwrap();
black_box(results)
});
});
}
criterion_group!(
bm25_benches,
bench_bm25_1k,
bench_bm25_10k,
bench_bm25_phrase_10k,
bench_bm25_keyword_10k
);
criterion_main!(bm25_benches);