#![allow(dead_code)]
use std::sync::atomic::{AtomicU64, Ordering};
use sysinfo::System;
#[cfg(target_os = "macos")]
mod macos_memory {
use std::mem::MaybeUninit;
type MachPort = u32;
type KernReturn = i32;
const HOST_VM_INFO64: i32 = 4;
const HOST_VM_INFO64_COUNT: u32 = 38; const KERN_SUCCESS: i32 = 0;
#[repr(C)]
#[derive(Debug, Default)]
struct VmStatistics64 {
free_count: u64,
active_count: u64,
inactive_count: u64,
wire_count: u64,
zero_fill_count: u64,
reactivations: u64,
pageins: u64,
pageouts: u64,
faults: u64,
cow_faults: u64,
lookups: u64,
hits: u64,
purges: u64,
purgeable_count: u64,
speculative_count: u64,
decompressions: u64,
compressions: u64,
swapins: u64,
swapouts: u64,
compressor_page_count: u64,
throttled_count: u64,
external_page_count: u64,
internal_page_count: u64,
total_uncompressed_pages_in_compressor: u64,
}
extern "C" {
fn mach_host_self() -> MachPort;
fn host_statistics64(
host: MachPort,
flavor: i32,
host_info: *mut VmStatistics64,
count: *mut u32,
) -> KernReturn;
static vm_page_size: usize;
}
pub fn get_available_memory() -> Option<(u64, u64)> {
unsafe {
let host = mach_host_self();
let page_size = vm_page_size as u64;
let mut vm_stats = MaybeUninit::<VmStatistics64>::zeroed();
let mut count = HOST_VM_INFO64_COUNT;
let result = host_statistics64(host, HOST_VM_INFO64, vm_stats.as_mut_ptr(), &mut count);
if result != KERN_SUCCESS {
return None;
}
let stats = vm_stats.assume_init();
let available_pages = stats.free_count
+ stats.inactive_count
+ stats.purgeable_count
+ stats.speculative_count;
let total_pages = stats.free_count
+ stats.active_count
+ stats.inactive_count
+ stats.wire_count
+ stats.compressor_page_count
+ stats.speculative_count;
let available_bytes = available_pages.saturating_mul(page_size);
let total_bytes = total_pages.saturating_mul(page_size);
Some((total_bytes, available_bytes))
}
}
}
const DEFAULT_THRESHOLD_PERCENT: f64 = 80.0;
const THRESHOLD_ENV_VAR: &str = "VIBESQL_MEMORY_THRESHOLD";
#[derive(Debug, Clone)]
pub struct MemoryStats {
pub total_bytes: u64,
pub used_bytes: u64,
pub available_bytes: u64,
pub usage_percent: f64,
}
#[derive(Debug, Clone)]
pub enum MemoryPressure {
Ok(MemoryStats),
High { stats: MemoryStats, threshold_percent: f64 },
}
impl MemoryPressure {
pub fn is_high(&self) -> bool {
matches!(self, MemoryPressure::High { .. })
}
pub fn stats(&self) -> &MemoryStats {
match self {
MemoryPressure::Ok(stats) => stats,
MemoryPressure::High { stats, .. } => stats,
}
}
}
pub struct MemoryMonitor {
threshold_percent: f64,
high_water_mark_bytes: AtomicU64,
system: System,
}
impl MemoryMonitor {
pub fn new() -> Self {
let threshold_percent = std::env::var(THRESHOLD_ENV_VAR)
.ok()
.and_then(|s| s.parse::<f64>().ok())
.unwrap_or(DEFAULT_THRESHOLD_PERCENT)
.clamp(10.0, 99.0);
Self {
threshold_percent,
high_water_mark_bytes: AtomicU64::new(0),
system: System::new_all(),
}
}
pub fn with_threshold(threshold_percent: f64) -> Self {
Self {
threshold_percent: threshold_percent.clamp(10.0, 99.0),
high_water_mark_bytes: AtomicU64::new(0),
system: System::new_all(),
}
}
pub fn current_stats(&mut self) -> MemoryStats {
self.system.refresh_memory();
let total = self.system.total_memory();
let sysinfo_available = self.system.available_memory();
#[cfg(target_os = "macos")]
let (total, available) = {
if sysinfo_available == 0 || (total > 0 && sysinfo_available < total / 100) {
if let Some((_native_total, native_available)) =
macos_memory::get_available_memory()
{
(total, native_available.min(total))
} else {
(total, sysinfo_available)
}
} else {
(total, sysinfo_available)
}
};
#[cfg(not(target_os = "macos"))]
let available = sysinfo_available;
let used = total.saturating_sub(available);
let usage_percent = if total > 0 { (used as f64 / total as f64) * 100.0 } else { 0.0 };
self.high_water_mark_bytes.fetch_max(used, Ordering::Relaxed);
MemoryStats {
total_bytes: total,
used_bytes: used,
available_bytes: available,
usage_percent,
}
}
pub fn check_pressure(&mut self) -> MemoryPressure {
let stats = self.current_stats();
if stats.usage_percent >= self.threshold_percent {
MemoryPressure::High { stats, threshold_percent: self.threshold_percent }
} else {
MemoryPressure::Ok(stats)
}
}
pub fn is_pressure_high(&mut self) -> bool {
self.check_pressure().is_high()
}
pub fn threshold_percent(&self) -> f64 {
self.threshold_percent
}
pub fn high_water_mark_bytes(&self) -> u64 {
self.high_water_mark_bytes.load(Ordering::Relaxed)
}
pub fn reset_high_water_mark(&self) {
self.high_water_mark_bytes.store(0, Ordering::Relaxed);
}
}
impl Default for MemoryMonitor {
fn default() -> Self {
Self::new()
}
}
pub fn compute_parallelism() -> usize {
if let Ok(val) = std::env::var("PARALLEL_QUERIES") {
if let Ok(n) = val.parse::<usize>() {
if n == 0 {
return 1; }
return n.clamp(1, 16);
}
}
let mut monitor = MemoryMonitor::new();
let stats = monitor.current_stats();
let free_percent = if stats.total_bytes > 0 {
(stats.available_bytes as f64 / stats.total_bytes as f64) * 100.0
} else {
0.0
};
let parallelism = if free_percent > 70.0 {
8
} else if free_percent > 50.0 {
4
} else if free_percent > 30.0 {
2
} else {
1
};
if std::env::var("PARALLEL_DEBUG").is_ok() {
eprintln!(
"[PARALLEL] Free memory: {:.1}% ({} / {}), parallelism: {}",
free_percent,
format_bytes(stats.available_bytes),
format_bytes(stats.total_bytes),
parallelism
);
}
parallelism
}
pub fn format_bytes(bytes: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = KB * 1024;
const GB: u64 = MB * 1024;
if bytes >= GB {
format!("{:.2} GB", bytes as f64 / GB as f64)
} else if bytes >= MB {
format!("{:.2} MB", bytes as f64 / MB as f64)
} else if bytes >= KB {
format!("{:.2} KB", bytes as f64 / KB as f64)
} else {
format!("{} B", bytes)
}
}
#[derive(Debug)]
pub enum GuardedResult<T> {
Success(T),
Skipped { reason: String, stats: MemoryStats },
}
impl<T> GuardedResult<T> {
pub fn was_skipped(&self) -> bool {
matches!(self, GuardedResult::Skipped { .. })
}
pub fn ok(self) -> Option<T> {
match self {
GuardedResult::Success(val) => Some(val),
GuardedResult::Skipped { .. } => None,
}
}
}
#[cfg(test)]
mod tests {
#[allow(unused_imports)]
use super::{format_bytes, MemoryMonitor};
#[test]
fn test_memory_monitor_creation() {
let monitor = MemoryMonitor::new();
assert!(monitor.threshold_percent() >= 10.0);
assert!(monitor.threshold_percent() <= 99.0);
}
#[test]
fn test_custom_threshold() {
let monitor = MemoryMonitor::with_threshold(50.0);
assert_eq!(monitor.threshold_percent(), 50.0);
}
#[test]
fn test_threshold_clamping() {
let low = MemoryMonitor::with_threshold(5.0);
assert_eq!(low.threshold_percent(), 10.0);
let high = MemoryMonitor::with_threshold(150.0);
assert_eq!(high.threshold_percent(), 99.0);
}
#[test]
fn test_current_stats() {
let mut monitor = MemoryMonitor::new();
let stats = monitor.current_stats();
assert!(stats.total_bytes > 0);
assert!(stats.usage_percent >= 0.0);
assert!(stats.usage_percent <= 100.0);
assert!(
stats.available_bytes > 0,
"available_bytes should not be 0 (was {}, total: {}, usage: {:.1}%)",
stats.available_bytes,
stats.total_bytes,
stats.usage_percent
);
assert!(
stats.usage_percent < 99.0,
"Memory usage should not be 100% on a normal system (was {:.1}%)",
stats.usage_percent
);
}
#[test]
fn test_high_water_mark() {
let mut monitor = MemoryMonitor::new();
let _ = monitor.current_stats();
let hwm1 = monitor.high_water_mark_bytes();
assert!(hwm1 > 0);
monitor.reset_high_water_mark();
assert_eq!(monitor.high_water_mark_bytes(), 0);
}
#[test]
fn test_format_bytes() {
assert_eq!(format_bytes(500), "500 B");
assert_eq!(format_bytes(1536), "1.50 KB");
assert_eq!(format_bytes(1_572_864), "1.50 MB");
assert_eq!(format_bytes(1_610_612_736), "1.50 GB");
}
#[test]
fn test_compute_parallelism() {
use super::compute_parallelism;
let parallelism = compute_parallelism();
assert!(
parallelism == 1 || parallelism == 2 || parallelism == 4 || parallelism == 8,
"parallelism should be 1, 2, 4, or 8, got {}",
parallelism
);
assert!(parallelism >= 1, "parallelism should be at least 1");
}
#[cfg(target_os = "macos")]
#[test]
fn test_macos_native_memory_detection() {
use super::macos_memory;
let result = macos_memory::get_available_memory();
assert!(result.is_some(), "macOS native memory detection should succeed");
let (total, available) = result.unwrap();
assert!(total > 0, "total memory should be positive");
assert!(available > 0, "available memory should be positive");
assert!(available <= total, "available should not exceed total");
let usage_percent = ((total - available) as f64 / total as f64) * 100.0;
assert!(
usage_percent < 99.0,
"Native macOS detection: usage should not be 100% (was {:.1}%)",
usage_percent
);
}
}