use crate::core::error::PlottingError;
use std::mem;
use std::ptr;
type DWORD = u32;
type DWORDLONG = u64;
type HANDLE = *mut std::ffi::c_void;
type BOOL = i32;
const TRUE: BOOL = 1;
const FALSE: BOOL = 0;
#[repr(C)]
struct MEMORYSTATUSEX {
dwLength: DWORD,
dwMemoryLoad: DWORD,
ullTotalPhys: DWORDLONG,
ullAvailPhys: DWORDLONG,
ullTotalPageFile: DWORDLONG,
ullAvailPageFile: DWORDLONG,
ullTotalVirtual: DWORDLONG,
ullAvailVirtual: DWORDLONG,
ullAvailExtendedVirtual: DWORDLONG,
}
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: u16,
wReserved: u16,
dwPageSize: DWORD,
lpMinimumApplicationAddress: *mut std::ffi::c_void,
lpMaximumApplicationAddress: *mut std::ffi::c_void,
dwActiveProcessorMask: usize,
dwNumberOfProcessors: DWORD,
dwProcessorType: DWORD,
dwAllocationGranularity: DWORD,
wProcessorLevel: u16,
wProcessorRevision: u16,
}
#[repr(C)]
struct PERFORMANCE_INFORMATION {
cb: DWORD,
CommitTotal: usize,
CommitLimit: usize,
CommitPeak: usize,
PhysicalTotal: usize,
PhysicalAvailable: usize,
SystemCache: usize,
KernelTotal: usize,
KernelPaged: usize,
KernelNonpaged: usize,
PageSize: usize,
HandleCount: DWORD,
ProcessCount: DWORD,
ThreadCount: DWORD,
}
unsafe extern "system" {
fn GlobalMemoryStatusEx(lpBuffer: *mut MEMORYSTATUSEX) -> BOOL;
fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO) -> ();
fn GetPerformanceInfo(pPerformanceInformation: *mut PERFORMANCE_INFORMATION, cb: DWORD)
-> BOOL;
fn GetCurrentProcess() -> HANDLE;
fn SetProcessWorkingSetSize(
hProcess: HANDLE,
dwMinimumWorkingSetSize: usize,
dwMaximumWorkingSetSize: usize,
) -> BOOL;
fn GetLogicalProcessorInformation(
Buffer: *mut std::ffi::c_void,
ReturnedLength: *mut DWORD,
) -> BOOL;
fn GetLargePageMinimum() -> usize;
fn VirtualAlloc(
lpAddress: *mut std::ffi::c_void,
dwSize: usize,
flAllocationType: DWORD,
flProtect: DWORD,
) -> *mut std::ffi::c_void;
fn VirtualFree(lpAddress: *mut std::ffi::c_void, dwSize: usize, dwFreeType: DWORD) -> BOOL;
}
const MEM_COMMIT: DWORD = 0x1000;
const MEM_RESERVE: DWORD = 0x2000;
const MEM_LARGE_PAGES: DWORD = 0x20000000;
const MEM_RELEASE: DWORD = 0x8000;
const PAGE_READWRITE: DWORD = 0x04;
pub fn get_total_memory() -> Result<u64, PlottingError> {
unsafe {
let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;
let result = GlobalMemoryStatusEx(&mut memory_status);
if result != FALSE {
Ok(memory_status.ullTotalPhys)
} else {
Err(PlottingError::SystemError(
"Failed to get total memory".to_string(),
))
}
}
}
pub fn get_available_memory() -> Result<u64, PlottingError> {
unsafe {
let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;
let result = GlobalMemoryStatusEx(&mut memory_status);
if result != FALSE {
Ok(memory_status.ullAvailPhys)
} else {
Err(PlottingError::SystemError(
"Failed to get available memory".to_string(),
))
}
}
}
pub fn get_memory_status() -> Result<WindowsMemoryStatus, PlottingError> {
unsafe {
let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;
let result = GlobalMemoryStatusEx(&mut memory_status);
if result != FALSE {
Ok(WindowsMemoryStatus {
memory_load: memory_status.dwMemoryLoad,
total_physical: memory_status.ullTotalPhys,
available_physical: memory_status.ullAvailPhys,
total_page_file: memory_status.ullTotalPageFile,
available_page_file: memory_status.ullAvailPageFile,
total_virtual: memory_status.ullTotalVirtual,
available_virtual: memory_status.ullAvailVirtual,
available_extended_virtual: memory_status.ullAvailExtendedVirtual,
})
} else {
Err(PlottingError::SystemError(
"Failed to get memory status".to_string(),
))
}
}
}
pub fn get_performance_info() -> Result<WindowsPerformanceInfo, PlottingError> {
unsafe {
let mut perf_info: PERFORMANCE_INFORMATION = mem::zeroed();
perf_info.cb = mem::size_of::<PERFORMANCE_INFORMATION>() as DWORD;
let result = GetPerformanceInfo(&mut perf_info, perf_info.cb);
if result != FALSE {
Ok(WindowsPerformanceInfo {
commit_total: perf_info.CommitTotal * perf_info.PageSize,
commit_limit: perf_info.CommitLimit * perf_info.PageSize,
commit_peak: perf_info.CommitPeak * perf_info.PageSize,
physical_total: perf_info.PhysicalTotal * perf_info.PageSize,
physical_available: perf_info.PhysicalAvailable * perf_info.PageSize,
system_cache: perf_info.SystemCache * perf_info.PageSize,
kernel_total: perf_info.KernelTotal * perf_info.PageSize,
kernel_paged: perf_info.KernelPaged * perf_info.PageSize,
kernel_nonpaged: perf_info.KernelNonpaged * perf_info.PageSize,
page_size: perf_info.PageSize,
handle_count: perf_info.HandleCount,
process_count: perf_info.ProcessCount,
thread_count: perf_info.ThreadCount,
})
} else {
Err(PlottingError::SystemError(
"Failed to get performance info".to_string(),
))
}
}
}
pub fn get_system_info() -> Result<WindowsSystemInfo, PlottingError> {
unsafe {
let mut sys_info: SYSTEM_INFO = mem::zeroed();
GetSystemInfo(&mut sys_info);
Ok(WindowsSystemInfo {
processor_architecture: sys_info.wProcessorArchitecture,
page_size: sys_info.dwPageSize as usize,
minimum_application_address: sys_info.lpMinimumApplicationAddress as usize,
maximum_application_address: sys_info.lpMaximumApplicationAddress as usize,
active_processor_mask: sys_info.dwActiveProcessorMask,
number_of_processors: sys_info.dwNumberOfProcessors as usize,
processor_type: sys_info.dwProcessorType,
allocation_granularity: sys_info.dwAllocationGranularity as usize,
processor_level: sys_info.wProcessorLevel,
processor_revision: sys_info.wProcessorRevision,
})
}
}
pub fn check_hugepage_support() -> bool {
check_large_page_support()
}
pub fn check_large_page_support() -> bool {
unsafe {
let min_large_page = GetLargePageMinimum();
min_large_page > 0
}
}
pub fn get_large_page_minimum() -> usize {
unsafe { GetLargePageMinimum() }
}
pub fn configure_working_set(
min_size: Option<usize>,
max_size: Option<usize>,
) -> Result<(), PlottingError> {
unsafe {
let process = GetCurrentProcess();
let min_ws = min_size.unwrap_or(0);
let max_ws = max_size.unwrap_or(0);
let result = SetProcessWorkingSetSize(process, min_ws, max_ws);
if result != FALSE {
Ok(())
} else {
Err(PlottingError::SystemError(
"Failed to configure working set size".to_string(),
))
}
}
}
pub fn get_numa_nodes() -> usize {
unsafe {
let mut buffer_length: DWORD = 0;
GetLogicalProcessorInformation(ptr::null_mut(), &mut buffer_length);
if buffer_length == 0 {
return 1; }
let mut buffer = vec![0u8; buffer_length as usize];
let result = GetLogicalProcessorInformation(
buffer.as_mut_ptr() as *mut std::ffi::c_void,
&mut buffer_length,
);
if result != FALSE {
let estimated_nodes = (buffer_length as usize / 48).max(1); estimated_nodes.min(64) } else {
1 }
}
}
pub fn allocate_large_pages(size: usize) -> Result<*mut std::ffi::c_void, PlottingError> {
if !check_large_page_support() {
return Err(PlottingError::SystemError(
"Large pages not supported".to_string(),
));
}
unsafe {
let ptr = VirtualAlloc(
ptr::null_mut(),
size,
MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
PAGE_READWRITE,
);
if ptr.is_null() {
Err(PlottingError::SystemError(
"Failed to allocate large pages".to_string(),
))
} else {
Ok(ptr)
}
}
}
pub fn free_large_pages(ptr: *mut std::ffi::c_void) -> Result<(), PlottingError> {
unsafe {
let result = VirtualFree(ptr, 0, MEM_RELEASE);
if result != FALSE {
Ok(())
} else {
Err(PlottingError::SystemError(
"Failed to free large pages".to_string(),
))
}
}
}
pub fn get_memory_pressure() -> Result<MemoryPressureLevel, PlottingError> {
let memory_status = get_memory_status()?;
let perf_info = get_performance_info()?;
let physical_pressure = memory_status.memory_load as f64 / 100.0;
let commit_pressure = perf_info.commit_total as f64 / perf_info.commit_limit as f64;
let overall_pressure = physical_pressure.max(commit_pressure);
let pressure_level = if overall_pressure > 0.95 {
MemoryPressureLevel::Critical
} else if overall_pressure > 0.85 {
MemoryPressureLevel::High
} else if overall_pressure > 0.70 {
MemoryPressureLevel::Medium
} else {
MemoryPressureLevel::Low
};
Ok(pressure_level)
}
#[derive(Debug, Clone)]
pub struct WindowsMemoryStatus {
pub memory_load: u32, pub total_physical: u64, pub available_physical: u64, pub total_page_file: u64, pub available_page_file: u64, pub total_virtual: u64, pub available_virtual: u64, pub available_extended_virtual: u64, }
#[derive(Debug, Clone)]
pub struct WindowsPerformanceInfo {
pub commit_total: usize, pub commit_limit: usize, pub commit_peak: usize, pub physical_total: usize, pub physical_available: usize, pub system_cache: usize, pub kernel_total: usize, pub kernel_paged: usize, pub kernel_nonpaged: usize, pub page_size: usize, pub handle_count: u32, pub process_count: u32, pub thread_count: u32, }
#[derive(Debug, Clone)]
pub struct WindowsSystemInfo {
pub processor_architecture: u16,
pub page_size: usize,
pub minimum_application_address: usize,
pub maximum_application_address: usize,
pub active_processor_mask: usize,
pub number_of_processors: usize,
pub processor_type: u32,
pub allocation_granularity: usize,
pub processor_level: u16,
pub processor_revision: u16,
}
#[derive(Debug, Clone)]
pub enum MemoryPressureLevel {
Low,
Medium,
High,
Critical,
}
pub fn get_windows_optimization_recommendations(
memory_status: &WindowsMemoryStatus,
perf_info: &WindowsPerformanceInfo,
) -> Vec<String> {
let mut recommendations = Vec::new();
if memory_status.memory_load > 85 {
recommendations
.push("High memory usage detected. Consider reducing memory consumption.".to_string());
}
let page_file_usage = (perf_info.commit_total as f64) / (perf_info.commit_limit as f64);
if page_file_usage > 0.8 {
recommendations.push(
"High page file usage. Consider increasing page file size or adding more RAM."
.to_string(),
);
}
let virtual_fragmentation = (memory_status.total_virtual - memory_status.available_virtual)
as f64
/ memory_status.total_virtual as f64;
if virtual_fragmentation > 0.7 {
recommendations.push(
"Virtual address space fragmentation detected. Consider process restart.".to_string(),
);
}
if check_large_page_support() && memory_status.total_physical > 8 * 1024 * 1024 * 1024 {
recommendations.push(
"Large pages supported. Consider using large pages for large allocations.".to_string(),
);
}
if perf_info.physical_available < perf_info.physical_total / 10 {
recommendations.push(
"Low available physical memory. Consider optimizing working set size.".to_string(),
);
}
recommendations
}
pub fn enable_low_fragmentation_heap() -> Result<(), PlottingError> {
Ok(())
}
pub fn get_heap_fragmentation_info() -> Result<HeapFragmentationInfo, PlottingError> {
Ok(HeapFragmentationInfo {
total_heap_size: 0,
committed_size: 0,
uncommitted_size: 0,
fragmentation_percentage: 0.0,
largest_free_block: 0,
})
}
pub fn check_memory_mapping_support() -> Result<bool, PlottingError> {
Ok(true)
}
#[derive(Debug, Clone)]
pub struct HeapFragmentationInfo {
pub total_heap_size: usize,
pub committed_size: usize,
pub uncommitted_size: usize,
pub fragmentation_percentage: f64,
pub largest_free_block: usize,
}