use std::thread::available_parallelism;
pub const FALLBACK_SYSTEM_MEMORY_BYTES: u64 = 4 * 1024 * 1024 * 1024;
pub const FALLBACK_CPU_CORES: usize = 4;
pub const MAX_SEGMENT_SIZE: u64 = 1u64 << 62;
#[must_use]
pub fn detect_system_memory() -> u64 {
#[cfg(target_vendor = "apple")]
{
use std::{mem::size_of, ptr::null_mut};
let mut mem: u64 = 0;
let mut len = size_of::<u64>();
let mib = [libc::CTL_HW, libc::HW_MEMSIZE];
if unsafe {
libc::sysctl(
mib.as_ptr() as *mut _,
2,
&mut mem as *mut _ as *mut _,
&mut len,
null_mut(),
0,
)
} == 0
&& mem > 0
{
return mem;
}
}
#[cfg(all(unix, not(target_vendor = "apple")))]
{
let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
if pages > 0 && page_size > 0 {
let mem = (pages as u64).saturating_mul(page_size as u64);
if mem > 0 {
return mem;
}
}
}
#[cfg(windows)]
{
#[repr(C)]
struct MemoryStatusEx {
dw_length: u32,
dw_memory_load: u32,
ull_total_phys: u64,
ull_avail_phys: u64,
ull_total_page_file: u64,
ull_avail_page_file: u64,
ull_total_virtual: u64,
ull_avail_virtual: u64,
ull_avail_extended_virtual: u64,
}
unsafe extern "system" {
fn GlobalMemoryStatusEx(lpBuffer: *mut MemoryStatusEx) -> i32;
}
let mut status = MemoryStatusEx {
dw_length: std::mem::size_of::<MemoryStatusEx>() as u32,
dw_memory_load: 0,
ull_total_phys: 0,
ull_avail_phys: 0,
ull_total_page_file: 0,
ull_avail_page_file: 0,
ull_total_virtual: 0,
ull_avail_virtual: 0,
ull_avail_extended_virtual: 0,
};
if unsafe { GlobalMemoryStatusEx(&mut status) } != 0 && status.ull_total_phys > 0 {
return status.ull_total_phys;
}
}
FALLBACK_SYSTEM_MEMORY_BYTES
}
#[must_use]
pub fn detect_cpu_cores() -> usize {
available_parallelism().map_or(FALLBACK_CPU_CORES, |n| n.get())
}