use std::collections::{HashMap, VecDeque};
use std::time::{Duration, Instant};
use super::config::{GPUAccelerationConfig, ProfilingConfig};
pub struct PerformanceProfiler {
pub config: ProfilingConfig,
pub cpu_profiler: CPUProfiler,
pub memory_profiler: MemoryProfiler,
pub io_profiler: IOProfiler,
pub metrics: PerformanceMetrics,
}
impl PerformanceProfiler {
#[must_use]
pub fn new(config: ProfilingConfig) -> Self {
Self {
config,
cpu_profiler: CPUProfiler::new(),
memory_profiler: MemoryProfiler::new(),
io_profiler: IOProfiler::new(),
metrics: PerformanceMetrics::default(),
}
}
pub fn start(&mut self) {
self.cpu_profiler.start();
self.memory_profiler.start();
self.io_profiler.start();
}
pub fn stop(&mut self) -> PerformanceMetrics {
self.cpu_profiler.stop();
self.memory_profiler.stop();
self.io_profiler.stop();
self.metrics.clone()
}
pub fn snapshot(&mut self) {
self.cpu_profiler.sample();
self.memory_profiler.sample();
self.io_profiler.sample();
}
}
#[derive(Debug)]
pub struct CPUProfiler {
pub cpu_samples: VecDeque<CPUSample>,
pub function_stats: HashMap<String, FunctionStatistics>,
pub config: CPUProfilingConfig,
pub is_active: bool,
}
impl CPUProfiler {
#[must_use]
pub fn new() -> Self {
Self {
cpu_samples: VecDeque::new(),
function_stats: HashMap::new(),
config: CPUProfilingConfig::default(),
is_active: false,
}
}
pub fn start(&mut self) {
self.is_active = true;
self.cpu_samples.clear();
}
pub fn stop(&mut self) {
self.is_active = false;
}
pub fn sample(&mut self) {
if !self.is_active {
return;
}
let sample = CPUSample {
timestamp: Instant::now(),
usage_percent: 0.0, active_threads: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
context_switches: 0,
};
self.cpu_samples.push_back(sample);
while self.cpu_samples.len() > self.config.max_samples {
self.cpu_samples.pop_front();
}
}
pub fn record_function_call(&mut self, function_name: &str, duration: Duration) {
let stats = self
.function_stats
.entry(function_name.to_string())
.or_insert_with(|| FunctionStatistics::new(function_name));
stats.call_count += 1;
stats.total_time += duration;
stats.average_time = stats.total_time / stats.call_count as u32;
if duration > stats.max_time {
stats.max_time = duration;
}
if stats.min_time == Duration::ZERO || duration < stats.min_time {
stats.min_time = duration;
}
}
#[must_use]
pub fn average_usage(&self) -> f64 {
if self.cpu_samples.is_empty() {
return 0.0;
}
let sum: f64 = self.cpu_samples.iter().map(|s| s.usage_percent).sum();
sum / self.cpu_samples.len() as f64
}
}
impl Default for CPUProfiler {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct CPUSample {
pub timestamp: Instant,
pub usage_percent: f64,
pub active_threads: usize,
pub context_switches: u64,
}
#[derive(Debug, Clone)]
pub struct FunctionStatistics {
pub function_name: String,
pub call_count: u64,
pub total_time: Duration,
pub average_time: Duration,
pub max_time: Duration,
pub min_time: Duration,
}
impl FunctionStatistics {
#[must_use]
pub fn new(function_name: &str) -> Self {
Self {
function_name: function_name.to_string(),
call_count: 0,
total_time: Duration::ZERO,
average_time: Duration::ZERO,
max_time: Duration::ZERO,
min_time: Duration::ZERO,
}
}
}
#[derive(Debug, Clone)]
pub struct CPUProfilingConfig {
pub max_samples: usize,
pub sampling_interval: Duration,
pub enable_function_profiling: bool,
}
impl Default for CPUProfilingConfig {
fn default() -> Self {
Self {
max_samples: 1000,
sampling_interval: Duration::from_millis(100),
enable_function_profiling: true,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct MemoryProfiler {
pub samples: VecDeque<MemorySample>,
pub is_active: bool,
}
impl MemoryProfiler {
#[must_use]
pub const fn new() -> Self {
Self {
samples: VecDeque::new(),
is_active: false,
}
}
pub fn start(&mut self) {
self.is_active = true;
self.samples.clear();
}
pub fn stop(&mut self) {
self.is_active = false;
}
pub fn sample(&mut self) {
if !self.is_active {
return;
}
let sample = MemorySample {
timestamp: Instant::now(),
heap_usage: 0,
stack_usage: 0,
total_allocated: 0,
};
self.samples.push_back(sample);
}
}
#[derive(Debug, Clone)]
pub struct MemorySample {
pub timestamp: Instant,
pub heap_usage: usize,
pub stack_usage: usize,
pub total_allocated: usize,
}
#[derive(Debug, Clone, Default)]
pub struct IOProfiler {
pub samples: VecDeque<IOSample>,
pub is_active: bool,
}
impl IOProfiler {
#[must_use]
pub const fn new() -> Self {
Self {
samples: VecDeque::new(),
is_active: false,
}
}
pub fn start(&mut self) {
self.is_active = true;
self.samples.clear();
}
pub fn stop(&mut self) {
self.is_active = false;
}
pub fn sample(&mut self) {
if !self.is_active {
return;
}
let sample = IOSample {
timestamp: Instant::now(),
bytes_read: 0,
bytes_written: 0,
io_operations: 0,
};
self.samples.push_back(sample);
}
}
#[derive(Debug, Clone)]
pub struct IOSample {
pub timestamp: Instant,
pub bytes_read: u64,
pub bytes_written: u64,
pub io_operations: u64,
}
#[derive(Debug, Clone, Default)]
pub struct PerformanceMetrics {
pub performance_score: f64,
pub cpu_utilization: f64,
pub memory_utilization: f64,
pub io_throughput: f64,
}
pub struct GPUAccelerator {
pub config: GPUAccelerationConfig,
pub devices: Vec<GPUDevice>,
pub memory_manager: GPUMemoryManager,
pub kernel_registry: KernelRegistry,
}
impl GPUAccelerator {
#[must_use]
pub fn new(config: GPUAccelerationConfig) -> Self {
Self {
config,
devices: Vec::new(),
memory_manager: GPUMemoryManager::new(),
kernel_registry: KernelRegistry::new(),
}
}
#[must_use]
pub fn is_available(&self) -> bool {
self.config.enable_gpu && !self.devices.is_empty()
}
#[must_use]
pub fn device_count(&self) -> usize {
self.devices.len()
}
#[must_use]
pub fn get_device(&self, device_id: usize) -> Option<&GPUDevice> {
self.devices.iter().find(|d| d.device_id == device_id)
}
pub fn detect_devices(&mut self) {
self.devices.clear();
}
}
#[derive(Debug)]
pub struct GPUDevice {
pub device_id: usize,
pub device_name: String,
pub compute_capability: (u32, u32),
pub total_memory: usize,
pub available_memory: usize,
pub status: GPUDeviceStatus,
}
impl GPUDevice {
#[must_use]
pub fn new(device_id: usize, device_name: String) -> Self {
Self {
device_id,
device_name,
compute_capability: (0, 0),
total_memory: 0,
available_memory: 0,
status: GPUDeviceStatus::Available,
}
}
#[must_use]
pub fn is_available(&self) -> bool {
self.status == GPUDeviceStatus::Available
}
#[must_use]
pub fn memory_utilization(&self) -> f64 {
if self.total_memory == 0 {
return 0.0;
}
(self.total_memory - self.available_memory) as f64 / self.total_memory as f64
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GPUDeviceStatus {
Available,
Busy,
Error,
Unsupported,
}
#[derive(Debug, Clone, Default)]
pub struct GPUMemoryManager {
pub allocated_buffers: HashMap<String, GPUBuffer>,
pub total_allocated: usize,
}
impl GPUMemoryManager {
#[must_use]
pub fn new() -> Self {
Self {
allocated_buffers: HashMap::new(),
total_allocated: 0,
}
}
pub fn allocate(&mut self, name: &str, size: usize) -> Result<(), String> {
let buffer = GPUBuffer {
name: name.to_string(),
size,
device_ptr: 0, };
self.allocated_buffers.insert(name.to_string(), buffer);
self.total_allocated += size;
Ok(())
}
pub fn free(&mut self, name: &str) -> Result<(), String> {
if let Some(buffer) = self.allocated_buffers.remove(name) {
self.total_allocated = self.total_allocated.saturating_sub(buffer.size);
Ok(())
} else {
Err(format!("Buffer {name} not found"))
}
}
}
#[derive(Debug, Clone)]
pub struct GPUBuffer {
pub name: String,
pub size: usize,
pub device_ptr: usize,
}
#[derive(Debug, Clone, Default)]
pub struct KernelRegistry {
pub kernels: HashMap<String, GPUKernel>,
}
impl KernelRegistry {
#[must_use]
pub fn new() -> Self {
Self {
kernels: HashMap::new(),
}
}
pub fn register(&mut self, name: &str, kernel: GPUKernel) {
self.kernels.insert(name.to_string(), kernel);
}
#[must_use]
pub fn get(&self, name: &str) -> Option<&GPUKernel> {
self.kernels.get(name)
}
}
#[derive(Debug, Clone)]
pub struct GPUKernel {
pub name: String,
pub block_size: usize,
pub grid_size: usize,
pub shared_memory: usize,
}
impl GPUKernel {
#[must_use]
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
block_size: 256,
grid_size: 1024,
shared_memory: 0,
}
}
}