项目文件夹

文件
2026-02-06 18:42:01 -05:00

177 行
5.8 KiB
Rust

//! Search precision benchmarks for implicit AND operator change.
//!
//! This benchmark suite measures the performance impact of changing the implicit
//! query operator from OR to AND. It verifies that the precision improvement
//! (33% → 100%) comes with no query latency regression.
//!
//! # Benchmarks
//!
//! - `query_two_words`: Measures latency for simple two-word queries
//! - `precision_calculation`: Measures precision metrics and filtering overhead
//! - `result_count`: Measures result set size impact
//!
//! # Running
//!
//! ```bash
//! cargo bench --bench search_precision_benchmark --features lex
//! ```
use criterion::{Criterion, criterion_group, criterion_main};
use memvid_core::{Memvid, PutOptions, SearchRequest};
use std::time::Instant;
/// Setup test corpus
fn setup_corpus(size: usize) -> std::path::PathBuf {
let temp_file = std::env::temp_dir().join(format!("bench_{}.mv2", size));
let _ = std::fs::remove_file(&temp_file);
let mut mem = Memvid::create(&temp_file).unwrap();
let topics = [
"machine learning neural networks",
"python programming development",
"machine learning with python",
"rust systems programming",
"web development javascript",
];
for i in 0..size {
let content = format!("Document {} about {}", i, topics[i % topics.len()]);
mem.put_bytes_with_options(
content.as_bytes(),
PutOptions::builder().title(format!("Doc {}", i)).build(),
)
.unwrap();
if (i + 1) % 100 == 0 {
mem.commit().unwrap();
}
}
mem.commit().unwrap();
temp_file
}
fn bench_query_latency(c: &mut Criterion) {
let corpus_path = setup_corpus(1000);
c.bench_function("query_two_words", |b| {
b.iter_custom(|iters| {
let mut total = std::time::Duration::ZERO;
for _ in 0..iters {
let mut mem = Memvid::open(&corpus_path).unwrap(); // FIX: mut
let start = Instant::now();
let _results = mem
.search(SearchRequest {
query: "machine learning".to_string(),
top_k: 10,
snippet_chars: 200,
uri: None,
scope: None,
cursor: None,
#[cfg(feature = "temporal_track")]
temporal: None,
as_of_frame: None,
as_of_ts: None,
no_sketch: false,
acl_context: None,
acl_enforcement_mode: memvid_core::types::AclEnforcementMode::Audit,
})
.unwrap();
total += start.elapsed();
}
total
});
});
std::fs::remove_file(&corpus_path).ok();
}
fn bench_precision(c: &mut Criterion) {
let corpus_path = setup_corpus(1000);
c.bench_function("precision_calculation", |b| {
b.iter_custom(|iters| {
let mut total = std::time::Duration::ZERO;
for _ in 0..iters {
let mut mem = Memvid::open(&corpus_path).unwrap(); // FIX: mut
let start = Instant::now();
let results = mem
.search(SearchRequest {
query: "machine python".to_string(),
top_k: 100,
snippet_chars: 200,
uri: None,
scope: None,
cursor: None,
#[cfg(feature = "temporal_track")]
temporal: None,
as_of_frame: None,
as_of_ts: None,
no_sketch: false,
acl_context: None,
acl_enforcement_mode: memvid_core::types::AclEnforcementMode::Audit,
})
.unwrap();
let _relevant = results
.hits
.iter()
.filter(|hit| {
let text = hit.text.to_lowercase();
text.contains("machine") && text.contains("python")
})
.count();
total += start.elapsed();
}
total
});
});
std::fs::remove_file(&corpus_path).ok();
}
fn bench_result_count(c: &mut Criterion) {
let corpus_path = setup_corpus(1000);
c.bench_function("result_count", |b| {
b.iter_custom(|iters| {
let mut total = std::time::Duration::ZERO;
for _ in 0..iters {
let mut mem = Memvid::open(&corpus_path).unwrap(); // FIX: mut
let start = Instant::now();
let results = mem
.search(SearchRequest {
query: "machine learning".to_string(),
top_k: 100,
snippet_chars: 200,
uri: None,
scope: None,
cursor: None,
#[cfg(feature = "temporal_track")]
temporal: None,
as_of_frame: None,
as_of_ts: None,
no_sketch: false,
acl_context: None,
acl_enforcement_mode: memvid_core::types::AclEnforcementMode::Audit,
})
.unwrap();
let _count = results.hits.len();
total += start.elapsed();
}
total
});
});
std::fs::remove_file(&corpus_path).ok();
}
criterion_group!(
benches,
bench_query_latency,
bench_precision,
bench_result_count
);
criterion_main!(benches);