Skip to main content

bench/
bench.rs

1use sifs::{SearchMode, SearchOptions, SifsIndex, metrics::peak_rss_mb};
2use std::time::Instant;
3
4fn main() -> anyhow::Result<()> {
5    let path = std::env::args().nth(1).unwrap_or_else(|| ".".to_owned());
6    let query = std::env::args()
7        .nth(2)
8        .unwrap_or_else(|| "hybrid search ranking".to_owned());
9    let runs = std::env::args()
10        .nth(3)
11        .and_then(|s| s.parse::<usize>().ok())
12        .unwrap_or(100);
13
14    let start = Instant::now();
15    let index = SifsIndex::from_path(&path)?;
16    let index_ms = start.elapsed().as_secs_f64() * 1000.0;
17
18    let mut uncached_times = Vec::with_capacity(runs);
19    let mut cached_times = Vec::with_capacity(runs);
20    let uncached = SearchOptions::new(10)
21        .with_mode(SearchMode::Hybrid)
22        .with_cache(false);
23    let cached = SearchOptions::new(10)
24        .with_mode(SearchMode::Hybrid)
25        .with_cache(true);
26    std::hint::black_box(index.search_with(&query, &uncached)?);
27    for _ in 0..runs {
28        let start = Instant::now();
29        let results = index.search_with(&query, &uncached)?;
30        std::hint::black_box(results);
31        uncached_times.push(start.elapsed().as_secs_f64() * 1000.0);
32    }
33    std::hint::black_box(index.search_with(&query, &cached)?);
34    for _ in 0..runs {
35        let start = Instant::now();
36        let results = index.search_with(&query, &cached)?;
37        std::hint::black_box(results);
38        cached_times.push(start.elapsed().as_secs_f64() * 1000.0);
39    }
40    uncached_times.sort_by(|a, b| a.partial_cmp(b).unwrap());
41    cached_times.sort_by(|a, b| a.partial_cmp(b).unwrap());
42    let uncached_p50 = uncached_times[uncached_times.len() / 2];
43    let uncached_p90 =
44        uncached_times[(uncached_times.len() * 9 / 10).min(uncached_times.len() - 1)];
45    let cached_p50 = cached_times[cached_times.len() / 2];
46    let cached_p90 = cached_times[(cached_times.len() * 9 / 10).min(cached_times.len() - 1)];
47    let stats = index.stats();
48    println!(
49        "cold_index_ms={index_ms:.3} warm_uncached_query_ms={uncached_p50:.3} warm_uncached_query_p90_ms={uncached_p90:.3} warm_cached_repeat_query_ms={cached_p50:.3} warm_cached_repeat_query_p90_ms={cached_p90:.3} peak_rss_mb={:.1} files={} chunks={}",
50        peak_rss_mb(),
51        stats.indexed_files,
52        index.chunks.len()
53    );
54    Ok(())
55}