#![allow(clippy::module_inception)]
use crate::data::memory::MemoryConfig;
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
pub struct PlatformOptimizer {
platform_info: PlatformInfo,
optimization_config: OptimizationConfig,
memory_limits: MemoryLimits,
performance_hints: Arc<RwLock<PerformanceHints>>,
}
#[derive(Debug, Clone)]
pub struct PlatformInfo {
pub os_type: OSType,
pub total_memory: u64,
pub available_memory: u64,
pub cpu_cores: usize,
pub cache_line_size: usize,
pub page_size: usize,
pub numa_nodes: usize,
pub supports_hugepages: bool,
pub supports_memory_mapping: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum OSType {
Linux,
FreeBSD,
MacOS,
Windows,
Other(String),
}
#[derive(Debug, Clone)]
pub struct OptimizationConfig {
pub use_hugepages: bool,
pub use_memory_mapping: bool,
pub prefer_numa_local: bool,
pub align_to_cache_lines: bool,
pub use_transparent_hugepages: bool,
pub memory_prefault: bool,
}
#[derive(Debug, Clone)]
pub struct MemoryLimits {
pub max_heap_size: Option<u64>,
pub warning_threshold: f32,
pub critical_threshold: f32,
pub swap_threshold: f32,
pub gc_trigger_threshold: f32,
}
#[derive(Debug, Clone)]
pub struct PerformanceHints {
pub optimal_chunk_size: usize,
pub recommended_alignment: usize,
pub prefetch_distance: usize,
pub concurrent_allocations: usize,
pub memory_bandwidth: Option<u64>,
pub latency_sensitive: bool,
}
impl PlatformOptimizer {
pub fn new() -> Result<Self, crate::core::error::PlottingError> {
let platform_info = detect_platform_info()?;
let optimization_config = create_optimization_config(&platform_info);
let memory_limits = calculate_memory_limits(&platform_info);
let performance_hints = generate_performance_hints(&platform_info);
Ok(Self {
platform_info,
optimization_config,
memory_limits,
performance_hints: Arc::new(RwLock::new(performance_hints)),
})
}
pub fn optimize_config(&self, base_config: &MemoryConfig) -> MemoryConfig {
let mut optimized = base_config.clone();
let memory_ratio =
(self.platform_info.available_memory as f64) / (8u64 * 1024 * 1024 * 1024) as f64;
optimized.max_pool_size = (optimized.max_pool_size as f64 * memory_ratio.min(8.0)) as usize;
optimized
}
pub fn get_performance_hints(&self) -> PerformanceHints {
self.performance_hints.read().unwrap().clone()
}
}
fn detect_platform_info() -> Result<PlatformInfo, crate::core::error::PlottingError> {
let os_type = detect_os_type();
let total_memory = platform::get_total_memory()?;
let available_memory = platform::get_available_memory()?;
let cpu_cores = num_cpus::get();
let numa_nodes = platform::get_numa_nodes();
let supports_hugepages = platform::check_hugepage_support();
let supports_memory_mapping = platform::check_memory_mapping_support()?;
Ok(PlatformInfo {
os_type,
total_memory,
available_memory,
cpu_cores,
cache_line_size: 64,
page_size: 4096,
numa_nodes,
supports_hugepages,
supports_memory_mapping,
})
}
fn detect_os_type() -> OSType {
#[cfg(target_os = "linux")]
return OSType::Linux;
#[cfg(target_os = "freebsd")]
return OSType::FreeBSD;
#[cfg(target_os = "macos")]
return OSType::MacOS;
#[cfg(target_os = "windows")]
return OSType::Windows;
#[cfg(not(any(
target_os = "linux",
target_os = "freebsd",
target_os = "macos",
target_os = "windows"
)))]
return OSType::Other(std::env::consts::OS.to_string());
}
fn create_optimization_config(platform_info: &PlatformInfo) -> OptimizationConfig {
OptimizationConfig {
use_hugepages: platform_info.supports_hugepages,
use_memory_mapping: platform_info.supports_memory_mapping,
prefer_numa_local: platform_info.numa_nodes > 1,
align_to_cache_lines: true,
use_transparent_hugepages: platform_info.os_type == OSType::Linux,
memory_prefault: platform_info.os_type != OSType::MacOS,
}
}
fn calculate_memory_limits(platform_info: &PlatformInfo) -> MemoryLimits {
let total_gb = platform_info.total_memory as f32 / (1024.0 * 1024.0 * 1024.0);
MemoryLimits {
max_heap_size: Some((platform_info.total_memory as f32 * 0.8) as u64),
warning_threshold: if total_gb > 16.0 { 0.7 } else { 0.6 },
critical_threshold: if total_gb > 16.0 { 0.85 } else { 0.8 },
swap_threshold: if total_gb > 8.0 { 0.9 } else { 0.85 },
gc_trigger_threshold: if total_gb > 32.0 { 0.75 } else { 0.65 },
}
}
fn generate_performance_hints(platform_info: &PlatformInfo) -> PerformanceHints {
let total_gb = platform_info.total_memory as f32 / (1024.0 * 1024.0 * 1024.0);
PerformanceHints {
optimal_chunk_size: if total_gb > 16.0 {
64 * 1024
} else {
32 * 1024
},
recommended_alignment: platform_info.cache_line_size,
prefetch_distance: platform_info.cache_line_size * 8,
concurrent_allocations: platform_info.cpu_cores.min(8),
memory_bandwidth: None,
latency_sensitive: total_gb <= 4.0,
}
}
static PLATFORM_OPTIMIZER: std::sync::OnceLock<PlatformOptimizer> = std::sync::OnceLock::new();
pub fn get_platform_optimizer() -> &'static PlatformOptimizer {
PLATFORM_OPTIMIZER.get_or_init(|| {
PlatformOptimizer::new().unwrap_or_else(|_| PlatformOptimizer {
platform_info: PlatformInfo {
os_type: detect_os_type(),
total_memory: 8 * 1024 * 1024 * 1024,
available_memory: 4 * 1024 * 1024 * 1024,
cpu_cores: num_cpus::get(),
cache_line_size: 64,
page_size: 4096,
numa_nodes: 1,
supports_hugepages: false,
supports_memory_mapping: true,
},
optimization_config: OptimizationConfig {
use_hugepages: false,
use_memory_mapping: true,
prefer_numa_local: false,
align_to_cache_lines: true,
use_transparent_hugepages: false,
memory_prefault: false,
},
memory_limits: MemoryLimits {
max_heap_size: Some(6 * 1024 * 1024 * 1024),
warning_threshold: 0.7,
critical_threshold: 0.85,
swap_threshold: 0.9,
gc_trigger_threshold: 0.75,
},
performance_hints: Arc::new(RwLock::new(PerformanceHints {
optimal_chunk_size: 32 * 1024,
recommended_alignment: 64,
prefetch_distance: 512,
concurrent_allocations: 4,
memory_bandwidth: None,
latency_sensitive: false,
})),
})
})
}
pub fn initialize_platform_optimization() -> Result<(), crate::core::error::PlottingError> {
let _optimizer = get_platform_optimizer();
Ok(())
}
#[cfg(target_os = "linux")]
#[path = "linux.rs"]
mod platform;
#[cfg(target_os = "freebsd")]
#[path = "freebsd.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path = "macos.rs"]
mod platform;
#[cfg(target_os = "windows")]
#[path = "windows.rs"]
mod platform;
#[cfg(not(any(
target_os = "linux",
target_os = "freebsd",
target_os = "macos",
target_os = "windows"
)))]
mod platform {
use crate::core::error::PlottingError;
pub fn get_total_memory() -> Result<u64, PlottingError> {
Ok(8 * 1024 * 1024 * 1024) }
pub fn get_available_memory() -> Result<u64, PlottingError> {
Ok(4 * 1024 * 1024 * 1024) }
pub fn get_numa_nodes() -> usize {
1
}
pub fn check_hugepage_support() -> bool {
false
}
pub fn check_large_page_support() -> bool {
false
}
pub fn check_memory_mapping_support() -> Result<bool, PlottingError> {
Ok(false)
}
}