hive_gpu/monitoring/
vram_monitor.rs1use crate::error::{Result, HiveGpuError};
7use crate::traits::{GpuMonitor, VramStats, VramBufferInfo};
8use std::collections::HashMap;
9use std::time::{SystemTime, UNIX_EPOCH};
10
11pub struct VramMonitor {
13 total_vram: usize,
15 allocated_vram: usize,
17 buffers: HashMap<usize, VramBufferInfo>,
19 next_buffer_id: usize,
21}
22
23impl VramMonitor {
24 pub fn new(total_vram: usize) -> Self {
26 Self {
27 total_vram,
28 allocated_vram: 0,
29 buffers: HashMap::new(),
30 next_buffer_id: 0,
31 }
32 }
33
34 pub fn allocate_buffer(&mut self, size: usize, buffer_type: crate::traits::BufferType) -> Result<usize> {
36 if self.allocated_vram + size > self.total_vram {
37 return Err(HiveGpuError::VramLimitExceeded {
38 requested: self.allocated_vram + size,
39 limit: self.total_vram,
40 });
41 }
42
43 let buffer_id = self.next_buffer_id;
44 self.next_buffer_id += 1;
45
46 let buffer_info = VramBufferInfo {
47 buffer_id,
48 size,
49 buffer_type,
50 allocated_at: SystemTime::now()
51 .duration_since(UNIX_EPOCH)
52 .unwrap()
53 .as_secs(),
54 };
55
56 self.buffers.insert(buffer_id, buffer_info);
57 self.allocated_vram += size;
58
59 Ok(buffer_id)
60 }
61
62 pub fn deallocate_buffer(&mut self, buffer_id: usize) -> Result<()> {
64 if let Some(buffer_info) = self.buffers.remove(&buffer_id) {
65 self.allocated_vram = self.allocated_vram.saturating_sub(buffer_info.size);
66 Ok(())
67 } else {
68 Err(HiveGpuError::Other(format!("Buffer {} not found", buffer_id)))
69 }
70 }
71
72 pub fn get_vram_stats(&self) -> VramStats {
74 VramStats {
75 total_vram: self.total_vram,
76 allocated_vram: self.allocated_vram,
77 available_vram: self.total_vram - self.allocated_vram,
78 utilization: self.allocated_vram as f32 / self.total_vram as f32,
79 buffer_count: self.buffers.len(),
80 }
81 }
82
83 pub fn validate_all_vram(&self) -> Result<()> {
85 let stats = self.get_vram_stats();
86
87 if stats.utilization > 0.95 {
88 return Err(HiveGpuError::VramLimitExceeded {
89 requested: stats.allocated_vram,
90 limit: (self.total_vram as f32 * 0.95) as usize,
91 });
92 }
93
94 Ok(())
95 }
96
97 pub fn generate_vram_report(&self) -> String {
99 let stats = self.get_vram_stats();
100 let mut report = String::new();
101
102 report.push_str(&format!("VRAM Report:\n"));
103 report.push_str(&format!(" Total VRAM: {:.2} MB\n", stats.total_vram as f64 / 1024.0 / 1024.0));
104 report.push_str(&format!(" Allocated: {:.2} MB\n", stats.allocated_vram as f64 / 1024.0 / 1024.0));
105 report.push_str(&format!(" Available: {:.2} MB\n", stats.available_vram as f64 / 1024.0 / 1024.0));
106 report.push_str(&format!(" Utilization: {:.1}%\n", stats.utilization * 100.0));
107 report.push_str(&format!(" Buffer Count: {}\n", stats.buffer_count));
108
109 let mut type_counts: HashMap<crate::traits::BufferType, (usize, usize)> = HashMap::new();
111 for buffer in self.buffers.values() {
112 let entry = type_counts.entry(buffer.buffer_type).or_insert((0, 0));
113 entry.0 += 1;
114 entry.1 += buffer.size;
115 }
116
117 report.push_str("\nBuffer Breakdown:\n");
118 for (buffer_type, (count, size)) in type_counts {
119 report.push_str(&format!(" {:?}: {} buffers, {:.2} MB\n",
120 buffer_type, count, size as f64 / 1024.0 / 1024.0));
121 }
122
123 report
124 }
125}
126
127impl GpuMonitor for VramMonitor {
128 fn get_vram_stats(&self) -> VramStats {
129 self.get_vram_stats()
130 }
131
132 fn validate_all_vram(&self) -> Result<()> {
133 self.validate_all_vram()
134 }
135
136 fn generate_vram_report(&self) -> String {
137 self.generate_vram_report()
138 }
139}
140
141pub struct VramValidator {
143 monitor: VramMonitor,
144 max_utilization: f32,
145}
146
147impl VramValidator {
148 pub fn new(total_vram: usize, max_utilization: f32) -> Self {
150 Self {
151 monitor: VramMonitor::new(total_vram),
152 max_utilization,
153 }
154 }
155
156 pub fn validate_allocation(&self, size: usize) -> Result<()> {
158 let stats = self.monitor.get_vram_stats();
159 let new_utilization = (stats.allocated_vram + size) as f32 / stats.total_vram as f32;
160
161 if new_utilization > self.max_utilization {
162 return Err(HiveGpuError::VramLimitExceeded {
163 requested: stats.allocated_vram + size,
164 limit: (stats.total_vram as f32 * self.max_utilization) as usize,
165 });
166 }
167
168 Ok(())
169 }
170}
171
172#[derive(Debug, Clone)]
174pub struct VramBenchmarkResult {
175 pub operation: String,
177 pub duration_ms: f64,
179 pub memory_allocated: usize,
181 pub utilization: f32,
183 pub throughput: f64,
185}