use std::sync::OnceLock;
use sysinfo::{MemoryRefreshKind, RefreshKind, System};
const BYTES_PER_CELL: u64 = 128;
const SORT_SHARE: f64 = 0.25;
const FILTER_SHARE: f64 = 0.05;
fn total_memory() -> u64 {
static TOTAL: OnceLock<u64> = OnceLock::new();
*TOTAL.get_or_init(|| {
let system = System::new_with_specifics(
RefreshKind::nothing().with_memory(MemoryRefreshKind::nothing().with_ram()),
);
match system.total_memory() {
0 => 4 << 30,
bytes => bytes,
}
})
}
pub fn scan_bytes() -> u64 {
const FLOOR: u64 = 8 << 20;
const CEILING: u64 = 64 << 20;
(total_memory() / 512).clamp(FLOOR, CEILING)
}
pub fn sort_cells() -> usize {
cells(SORT_SHARE)
}
pub fn filter_rows() -> usize {
let bytes = (total_memory() as f64 * FILTER_SHARE) as u64;
(bytes / size_of::<usize>() as u64).max(1_000_000) as usize
}
fn cells(share: f64) -> usize {
let bytes = (total_memory() as f64 * share) as u64;
(bytes / BYTES_PER_CELL).max(1_000_000) as usize
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_bounds_follow_the_machine_and_stay_sane() {
let total = total_memory();
assert!(total > 0, "some memory was reported");
let sort = sort_cells();
let filter = filter_rows();
assert!(
sort >= 1_000_000,
"a small machine can still sort something"
);
assert!(filter >= 1_000_000);
assert!((sort as u64).saturating_mul(BYTES_PER_CELL) <= total);
assert!((filter as u64).saturating_mul(8) <= total);
assert!(
sort > filter / 100,
"the two are the same order of magnitude"
);
}
#[test]
fn the_estimate_covers_what_was_measured() {
let measured = [
(10_000_000u64, 349_323_264u64), (10_000_000, 815_759_360), (50_000_000, 2_321_088_512), ];
for (cells, peak) in measured {
assert!(
cells * BYTES_PER_CELL >= peak,
"{cells} cells estimated at {} but cost {peak}",
cells * BYTES_PER_CELL
);
}
}
}