#![allow(dead_code)]
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
use codenexus::storage::StorageConnection;
use sysinfo::{Pid, System};
use tempfile::TempDir;
const LANGUAGES: &[&str] = &["rs", "c", "f90", "py", "ts"];
#[must_use]
pub fn generate_large_repo(file_count: usize) -> TempDir {
let dir = TempDir::new().expect("tempdir for large repo");
for i in 0..file_count {
let ext = LANGUAGES[i % LANGUAGES.len()];
let path = dir.path().join(format!("file_{i}.{ext}"));
std::fs::write(&path, minimal_symbol(ext, i)).expect("write fixture file");
}
dir
}
fn minimal_symbol(ext: &str, i: usize) -> String {
match ext {
"rs" => format!("fn func_{i}() {{}}\n"),
"c" => format!("int func_{i}(void) {{ return {i}; }}\n"),
"f90" => format!(" subroutine sub_{i}()\n end subroutine sub_{i}\n"),
"py" => format!("def func_{i}():\n return {i}\n"),
"ts" => format!("function func_{i}(): number {{ return {i}; }}\n"),
other => panic!("unsupported fixture extension: {other}"),
}
}
pub fn open_test_db() -> (TempDir, StorageConnection) {
let dir = TempDir::new().expect("tempdir for test db");
let db_path = dir.path().join("bench.db");
let conn = StorageConnection::open(&db_path).expect("open test db");
(dir, conn)
}
pub fn measure_peak_rss<F: FnOnce()>(f: F) -> u64 {
let peak: Arc<AtomicU64> = Arc::new(AtomicU64::new(0));
let stop: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let peak_worker = Arc::clone(&peak);
let stop_worker = Arc::clone(&stop);
let handle = std::thread::spawn(move || {
let mut sys = System::new();
let pid: Pid = Pid::from(std::process::id() as usize);
while !stop_worker.load(Ordering::SeqCst) {
sys.refresh_process(pid);
if let Some(proc_info) = sys.process(pid) {
let rss = proc_info.memory();
peak_worker.fetch_max(rss, Ordering::SeqCst);
}
std::thread::sleep(Duration::from_millis(100));
}
});
f();
stop.store(true, Ordering::SeqCst);
let _ = handle.join();
peak.load(Ordering::SeqCst)
}