audit fix and code stability improvement

This commit is contained in:
2026-02-26 16:09:44 +01:00
parent 07ccf7ccc7
commit f76acd6256
5 changed files with 53 additions and 21 deletions

View File

@@ -38,7 +38,7 @@ impl OptimizerEngine {
Self { window_size } Self { window_size }
} }
/// Applies a simple moving average (SMA) filter to a stream of values. /// Applies a simple moving average (SMA) filter with outlier rejection.
pub fn smooth(&self, data: &[f32]) -> Vec<f32> { pub fn smooth(&self, data: &[f32]) -> Vec<f32> {
if data.is_empty() { return vec![]; } if data.is_empty() { return vec![]; }
let mut smoothed = Vec::with_capacity(data.len()); let mut smoothed = Vec::with_capacity(data.len());
@@ -46,8 +46,19 @@ impl OptimizerEngine {
for i in 0..data.len() { for i in 0..data.len() {
let start = if i < self.window_size { 0 } else { i - self.window_size + 1 }; let start = if i < self.window_size { 0 } else { i - self.window_size + 1 };
let end = i + 1; let end = i + 1;
let sum: f32 = data[start..end].iter().sum();
smoothed.push(sum / (end - start) as f32); // Outlier rejection: only average values within a reasonable range
let window = &data[start..end];
let avg: f32 = window.iter().sum::<f32>() / window.len() as f32;
let filtered: Vec<f32> = window.iter()
.filter(|&&v| (v - avg).abs() < 20.0) // Reject spikes > 20 units
.cloned().collect();
if filtered.is_empty() {
smoothed.push(avg);
} else {
smoothed.push(filtered.iter().sum::<f32>() / filtered.len() as f32);
}
} }
smoothed smoothed
} }
@@ -55,11 +66,9 @@ impl OptimizerEngine {
/// Calculates Thermal Resistance: R_theta = (T_core - T_ambient) / P_package /// Calculates Thermal Resistance: R_theta = (T_core - T_ambient) / P_package
pub fn calculate_thermal_resistance(&self, profile: &ThermalProfile) -> f32 { pub fn calculate_thermal_resistance(&self, profile: &ThermalProfile) -> f32 {
profile.points.iter() profile.points.iter()
.filter(|p| p.power_w > 1.0 && p.temp_c > 30.0) // Filter invalid data
.max_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal)) .max_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal))
.map(|p| { .map(|p| (p.temp_c - profile.ambient_temp) / p.power_w)
if p.power_w < 1.0 { 0.0 }
else { (p.temp_c - profile.ambient_temp) / p.power_w }
})
.unwrap_or(0.0) .unwrap_or(0.0)
} }
@@ -73,11 +82,16 @@ impl OptimizerEngine {
/// Finds the "Silicon Knee" - the point where performance per watt (efficiency) /// Finds the "Silicon Knee" - the point where performance per watt (efficiency)
/// starts to diminish significantly and thermal density spikes. /// starts to diminish significantly and thermal density spikes.
pub fn find_silicon_knee(&self, profile: &ThermalProfile) -> f32 { pub fn find_silicon_knee(&self, profile: &ThermalProfile) -> f32 {
if profile.points.len() < 3 { let valid_points: Vec<_> = profile.points.iter()
.filter(|p| p.power_w > 5.0 && p.temp_c > 40.0) // Filter idle/noise
.cloned()
.collect();
if valid_points.len() < 3 {
return profile.points.last().map(|p| p.power_w).unwrap_or(15.0); return profile.points.last().map(|p| p.power_w).unwrap_or(15.0);
} }
let mut points = profile.points.clone(); let mut points = valid_points;
points.sort_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal)); points.sort_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal));
let mut best_pl = points[0].power_w; let mut best_pl = points[0].power_w;

View File

@@ -229,7 +229,7 @@ fn main() -> Result<()> {
while let Ok(new_state) = telemetry_rx.try_recv() { while let Ok(new_state) = telemetry_rx.try_recv() {
if let Some(log) = &new_state.log_event { if let Some(log) = &new_state.log_event {
ui_state.logs.push(log.clone()); ui_state.add_log(log.clone());
debug!("Backend Log: {}", log); debug!("Backend Log: {}", log);
} else { } else {
ui_state.update(&new_state); ui_state.update(&new_state);

View File

@@ -7,7 +7,6 @@ use sysinfo::System;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex; use std::sync::Mutex;
use std::path::PathBuf;
use crate::sal::traits::{PlatformSal, AuditStep, SafetyStatus}; use crate::sal::traits::{PlatformSal, AuditStep, SafetyStatus};
use crate::sal::heuristic::discovery::SystemFactSheet; use crate::sal::heuristic::discovery::SystemFactSheet;
@@ -80,6 +79,21 @@ impl BenchmarkOrchestrator {
// Start Watchdog Monitor // Start Watchdog Monitor
let _watchdog_handle = self.spawn_watchdog_monitor(); let _watchdog_handle = self.spawn_watchdog_monitor();
// Use a closure to ensure cleanup always runs
let result = self.execute_benchmark();
// --- MANDATORY CLEANUP ---
self.log("Benchmark sequence finished. Restoring hardware defaults...")?;
let _ = self.workload.stop();
if let Err(e) = self.sal.restore() {
anyhow::bail!("CRITICAL: Failed to restore hardware state: {}", e);
}
self.log("✓ Hardware state restored.")?;
result
}
fn execute_benchmark(&mut self) -> Result<OptimizationResult> {
// Phase 1: Audit & Baseline // Phase 1: Audit & Baseline
self.phase = BenchmarkPhase::Auditing; self.phase = BenchmarkPhase::Auditing;
for step in self.sal.audit() { for step in self.sal.audit() {
@@ -208,9 +222,6 @@ impl BenchmarkOrchestrator {
res.config_paths.insert("i8kmon".to_string(), i8k_path.clone()); res.config_paths.insert("i8kmon".to_string(), i8k_path.clone());
} }
self.sal.restore()?;
self.log("✓ Environment restored.")?;
Ok(res) Ok(res)
} }
@@ -228,9 +239,7 @@ impl BenchmarkOrchestrator {
abort.store(true, Ordering::SeqCst); abort.store(true, Ordering::SeqCst);
break; break;
} }
Ok(SafetyStatus::Warning(_msg)) | Ok(SafetyStatus::Critical(_msg)) => { Ok(SafetyStatus::Warning(_msg)) | Ok(SafetyStatus::Critical(_msg)) => {}
// Send warning log to UI
}
Ok(SafetyStatus::Nominal) => {} Ok(SafetyStatus::Nominal) => {}
Err(e) => { Err(e) => {
*reason_store.lock().unwrap() = Some(format!("Watchdog Sensor Failure: {}", e)); *reason_store.lock().unwrap() = Some(format!("Watchdog Sensor Failure: {}", e));

View File

@@ -108,7 +108,6 @@ impl PreflightAuditor for DellXps9380Sal {
} }
}); });
// Tool availability check
let tool_check = self.fact_sheet.paths.tools.contains_key("dell_fan_ctrl"); let tool_check = self.fact_sheet.paths.tools.contains_key("dell_fan_ctrl");
steps.push(AuditStep { steps.push(AuditStep {
description: "Dell Fan Control Tool".to_string(), description: "Dell Fan Control Tool".to_string(),
@@ -125,6 +124,7 @@ impl EnvironmentGuard for DellXps9380Sal {
let mut suppressed = self.suppressed_services.lock().unwrap(); let mut suppressed = self.suppressed_services.lock().unwrap();
for s in services { for s in services {
if Command::new("systemctl").args(["is-active", "--quiet", s]).status()?.success() { if Command::new("systemctl").args(["is-active", "--quiet", s]).status()?.success() {
debug!("Suppressing service: {}", s);
Command::new("systemctl").args(["stop", s]).status()?; Command::new("systemctl").args(["stop", s]).status()?;
suppressed.push(s.to_string()); suppressed.push(s.to_string());
} }

View File

@@ -7,20 +7,29 @@ use ratatui::{
Frame, Frame,
prelude::Stylize, prelude::Stylize,
}; };
use std::collections::VecDeque;
use crate::mediator::TelemetryState; use crate::mediator::TelemetryState;
use crate::ui::theme::*; use crate::ui::theme::*;
/// DashboardState maintains UI-specific state that isn't part of the core telemetry, /// DashboardState maintains UI-specific state that isn't part of the core telemetry,
/// such as the accumulated diagnostic logs. /// such as the accumulated diagnostic logs.
pub struct DashboardState { pub struct DashboardState {
pub logs: Vec<String>, pub logs: VecDeque<String>,
} }
impl DashboardState { impl DashboardState {
pub fn new() -> Self { pub fn new() -> Self {
Self { let mut logs = VecDeque::with_capacity(100);
logs: vec!["ember-tune Initialized.".to_string()], logs.push_back("ember-tune Initialized.".to_string());
Self { logs }
}
/// Adds a log message and ensures the buffer does not exceed capacity.
pub fn add_log(&mut self, msg: String) {
if self.logs.len() >= 100 {
self.logs.pop_front();
} }
self.logs.push_back(msg);
} }
/// Updates the UI state based on new telemetry. /// Updates the UI state based on new telemetry.