use std::path::{Path, PathBuf};
use roaring::RoaringBitmap;
pub(super) fn calibrate_threshold(indexed_paths: &[PathBuf]) -> f64 {
const DEFAULT: f64 = 0.10;
const SCAN_SAMPLE: usize = 100;
const BITMAP_ENTRIES: u32 = 10_000;
const BITMAP_REPS: u32 = 100;
let total = indexed_paths.len();
if total == 0 {
return DEFAULT;
}
let sample_count = SCAN_SAMPLE.min(total);
let stride = (total / sample_count).max(1);
let sample_paths: Vec<&Path> = (0..sample_count)
.map(|i| indexed_paths[(i * stride).min(total - 1)].as_path())
.collect();
for path in &sample_paths {
let _ = std::fs::read(path);
}
let mut docs_read = 0usize;
let mut scan_elapsed_ns = 0u128;
for path in &sample_paths {
let t0 = std::time::Instant::now();
if std::fs::read(path).is_ok() {
docs_read += 1;
scan_elapsed_ns += t0.elapsed().as_nanos();
}
}
if docs_read == 0 || scan_elapsed_ns == 0 {
return DEFAULT;
}
let scan_ns_per_doc = (scan_elapsed_ns / docs_read as u128) as u64;
let a: RoaringBitmap = (0..BITMAP_ENTRIES).collect();
let b: RoaringBitmap = (0..BITMAP_ENTRIES * 2).step_by(2).collect();
let t1 = std::time::Instant::now();
for _ in 0..BITMAP_REPS {
let _ = &a & &b;
}
let posting_elapsed_ns = t1.elapsed().as_nanos();
let total_entries_processed = BITMAP_ENTRIES as u64 * BITMAP_REPS as u64 * 2;
if posting_elapsed_ns == 0 {
return DEFAULT;
}
let posting_ns_per_entry = (posting_elapsed_ns / total_entries_processed as u128) as u64;
if posting_ns_per_entry == 0 {
return 0.50;
}
let threshold = scan_ns_per_doc as f64 / (scan_ns_per_doc + posting_ns_per_entry) as f64;
threshold.clamp(0.01, 0.50)
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn calibrate_threshold_empty_paths_returns_default() {
let threshold = calibrate_threshold(&[]);
assert_eq!(
threshold, 0.10,
"empty path list must return default threshold 0.10, got {threshold}"
);
}
#[test]
fn calibrate_threshold_returns_clamped_value() {
let repo = TempDir::new().unwrap();
let mut absolute_paths = Vec::new();
for i in 0..5 {
let abs = repo.path().join(format!("f{i}.rs"));
std::fs::write(&abs, format!("fn test_{i}() {{}}\n")).unwrap();
absolute_paths.push(abs);
}
let threshold = calibrate_threshold(&absolute_paths);
assert!(
(0.01..=0.50).contains(&threshold),
"threshold {threshold} outside [0.01, 0.50]"
);
}
}