[PERF] Host Debug Overlay Isolation

This commit is contained in:
bQUARKz 2026-04-10 12:42:15 +01:00
parent 47ab664280
commit b8d33c9e02
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
8 changed files with 83 additions and 29 deletions

View File

@ -1,7 +1,7 @@
use crate::log::{LogEvent, LogLevel, LogSource}; use crate::log::{LogEvent, LogLevel, LogSource};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
pub struct LogService { pub struct LogService {
events: VecDeque<LogEvent>, events: VecDeque<LogEvent>,

View File

@ -1,6 +1,6 @@
use crate::log::{LogLevel, LogService, LogSource}; use crate::log::{LogLevel, LogService, LogSource};
use std::sync::atomic::{AtomicU32, AtomicU64, AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicU32, AtomicU64, AtomicUsize, Ordering};
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct TelemetryFrame { pub struct TelemetryFrame {
@ -64,10 +64,7 @@ pub struct AtomicTelemetry {
impl AtomicTelemetry { impl AtomicTelemetry {
pub fn new(logs_count: Arc<AtomicU32>) -> Self { pub fn new(logs_count: Arc<AtomicU32>) -> Self {
Self { Self { logs_count, ..Default::default() }
logs_count,
..Default::default()
}
} }
/// Snapshots the current atomic state into a TelemetryFrame. /// Snapshots the current atomic state into a TelemetryFrame.
@ -92,6 +89,23 @@ impl AtomicTelemetry {
vm_steps: self.vm_steps.load(Ordering::Relaxed), vm_steps: self.vm_steps.load(Ordering::Relaxed),
} }
} }
pub fn reset(&self) {
self.frame_index.store(0, Ordering::Relaxed);
self.cycles_used.store(0, Ordering::Relaxed);
self.syscalls.store(0, Ordering::Relaxed);
self.host_cpu_time_us.store(0, Ordering::Relaxed);
self.completed_logical_frames.store(0, Ordering::Relaxed);
self.violations.store(0, Ordering::Relaxed);
self.gfx_used_bytes.store(0, Ordering::Relaxed);
self.gfx_inflight_bytes.store(0, Ordering::Relaxed);
self.gfx_slots_occupied.store(0, Ordering::Relaxed);
self.audio_used_bytes.store(0, Ordering::Relaxed);
self.audio_inflight_bytes.store(0, Ordering::Relaxed);
self.audio_slots_occupied.store(0, Ordering::Relaxed);
self.heap_used_bytes.store(0, Ordering::Relaxed);
self.vm_steps.store(0, Ordering::Relaxed);
}
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]

View File

@ -9,11 +9,11 @@ use prometeu_hal::log::{LogLevel, LogSource};
use prometeu_hal::sprite::Sprite; use prometeu_hal::sprite::Sprite;
use prometeu_hal::syscalls::Syscall; use prometeu_hal::syscalls::Syscall;
use prometeu_hal::vm_fault::VmFault; use prometeu_hal::vm_fault::VmFault;
use std::sync::atomic::Ordering;
use prometeu_hal::{ use prometeu_hal::{
AudioOpStatus, GfxOpStatus, HostContext, HostReturn, NativeInterface, SyscallId, expect_bool, AudioOpStatus, GfxOpStatus, HostContext, HostReturn, NativeInterface, SyscallId, expect_bool,
expect_int, expect_int,
}; };
use std::sync::atomic::Ordering;
impl VirtualMachineRuntime { impl VirtualMachineRuntime {
fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> { fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> {

View File

@ -89,6 +89,7 @@ impl VirtualMachineRuntime {
self.logical_frame_active = false; self.logical_frame_active = false;
self.logical_frame_remaining_cycles = 0; self.logical_frame_remaining_cycles = 0;
self.last_frame_cpu_time_us = 0; self.last_frame_cpu_time_us = 0;
self.atomic_telemetry.reset();
self.open_files.clear(); self.open_files.clear();
self.next_handle = 1; self.next_handle = 1;

View File

@ -16,6 +16,7 @@ use prometeu_hal::glyph_bank::GLYPH_BANK_PALETTE_COUNT_V1;
use prometeu_hal::syscalls::caps; use prometeu_hal::syscalls::caps;
use prometeu_vm::VmInitError; use prometeu_vm::VmInitError;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::Ordering;
#[derive(Default)] #[derive(Default)]
struct MemFsBackend { struct MemFsBackend {

View File

@ -135,17 +135,33 @@ impl VirtualMachineRuntime {
// 1. Snapshot full telemetry at logical frame end // 1. Snapshot full telemetry at logical frame end
let gfx_stats = hw.assets().bank_info(BankType::GLYPH); let gfx_stats = hw.assets().bank_info(BankType::GLYPH);
self.atomic_telemetry.gfx_used_bytes.store(gfx_stats.used_bytes, Ordering::Relaxed); self.atomic_telemetry
self.atomic_telemetry.gfx_inflight_bytes.store(gfx_stats.inflight_bytes, Ordering::Relaxed); .gfx_used_bytes
self.atomic_telemetry.gfx_slots_occupied.store(gfx_stats.slots_occupied as u32, Ordering::Relaxed); .store(gfx_stats.used_bytes, Ordering::Relaxed);
self.atomic_telemetry
.gfx_inflight_bytes
.store(gfx_stats.inflight_bytes, Ordering::Relaxed);
self.atomic_telemetry
.gfx_slots_occupied
.store(gfx_stats.slots_occupied as u32, Ordering::Relaxed);
let audio_stats = hw.assets().bank_info(BankType::SOUNDS); let audio_stats = hw.assets().bank_info(BankType::SOUNDS);
self.atomic_telemetry.audio_used_bytes.store(audio_stats.used_bytes, Ordering::Relaxed); self.atomic_telemetry
self.atomic_telemetry.audio_inflight_bytes.store(audio_stats.inflight_bytes, Ordering::Relaxed); .audio_used_bytes
self.atomic_telemetry.audio_slots_occupied.store(audio_stats.slots_occupied as u32, Ordering::Relaxed); .store(audio_stats.used_bytes, Ordering::Relaxed);
self.atomic_telemetry
.audio_inflight_bytes
.store(audio_stats.inflight_bytes, Ordering::Relaxed);
self.atomic_telemetry
.audio_slots_occupied
.store(audio_stats.slots_occupied as u32, Ordering::Relaxed);
self.atomic_telemetry.heap_used_bytes.store(vm.heap().used_bytes.load(Ordering::Relaxed), Ordering::Relaxed); self.atomic_telemetry
self.atomic_telemetry.host_cpu_time_us.store(start.elapsed().as_micros() as u64, Ordering::Relaxed); .heap_used_bytes
.store(vm.heap().used_bytes.load(Ordering::Relaxed), Ordering::Relaxed);
self.atomic_telemetry
.host_cpu_time_us
.store(start.elapsed().as_micros() as u64, Ordering::Relaxed);
let ts_ms = self.boot_time.elapsed().as_millis() as u64; let ts_ms = self.boot_time.elapsed().as_millis() as u64;
let telemetry_snapshot = self.atomic_telemetry.snapshot(); let telemetry_snapshot = self.atomic_telemetry.snapshot();
@ -157,7 +173,9 @@ impl VirtualMachineRuntime {
) as u32; ) as u32;
self.atomic_telemetry.violations.store(violations, Ordering::Relaxed); self.atomic_telemetry.violations.store(violations, Ordering::Relaxed);
self.atomic_telemetry.completed_logical_frames.fetch_add(1, Ordering::Relaxed); self.atomic_telemetry
.completed_logical_frames
.fetch_add(1, Ordering::Relaxed);
self.log_service.reset_count(); self.log_service.reset_count();
@ -190,18 +208,30 @@ impl VirtualMachineRuntime {
if self.inspection_active { if self.inspection_active {
let gfx_stats = hw.assets().bank_info(BankType::GLYPH); let gfx_stats = hw.assets().bank_info(BankType::GLYPH);
self.atomic_telemetry.gfx_used_bytes.store(gfx_stats.used_bytes, Ordering::Relaxed); self.atomic_telemetry.gfx_used_bytes.store(gfx_stats.used_bytes, Ordering::Relaxed);
self.atomic_telemetry.gfx_inflight_bytes.store(gfx_stats.inflight_bytes, Ordering::Relaxed); self.atomic_telemetry
self.atomic_telemetry.gfx_slots_occupied.store(gfx_stats.slots_occupied as u32, Ordering::Relaxed); .gfx_inflight_bytes
.store(gfx_stats.inflight_bytes, Ordering::Relaxed);
self.atomic_telemetry
.gfx_slots_occupied
.store(gfx_stats.slots_occupied as u32, Ordering::Relaxed);
let audio_stats = hw.assets().bank_info(BankType::SOUNDS); let audio_stats = hw.assets().bank_info(BankType::SOUNDS);
self.atomic_telemetry.audio_used_bytes.store(audio_stats.used_bytes, Ordering::Relaxed); self.atomic_telemetry.audio_used_bytes.store(audio_stats.used_bytes, Ordering::Relaxed);
self.atomic_telemetry.audio_inflight_bytes.store(audio_stats.inflight_bytes, Ordering::Relaxed); self.atomic_telemetry
self.atomic_telemetry.audio_slots_occupied.store(audio_stats.slots_occupied as u32, Ordering::Relaxed); .audio_inflight_bytes
.store(audio_stats.inflight_bytes, Ordering::Relaxed);
self.atomic_telemetry
.audio_slots_occupied
.store(audio_stats.slots_occupied as u32, Ordering::Relaxed);
self.atomic_telemetry.heap_used_bytes.store(vm.heap().used_bytes.load(Ordering::Relaxed), Ordering::Relaxed); self.atomic_telemetry
.heap_used_bytes
.store(vm.heap().used_bytes.load(Ordering::Relaxed), Ordering::Relaxed);
self.atomic_telemetry.frame_index.store(self.logical_frame_index, Ordering::Relaxed); self.atomic_telemetry.frame_index.store(self.logical_frame_index, Ordering::Relaxed);
self.atomic_telemetry.host_cpu_time_us.store(start.elapsed().as_micros() as u64, Ordering::Relaxed); self.atomic_telemetry
.host_cpu_time_us
.store(start.elapsed().as_micros() as u64, Ordering::Relaxed);
} }
None None

View File

@ -198,15 +198,19 @@ impl HostRunner {
// Snapshot does not include violations, as they are part of certification (logical end of frame) // Snapshot does not include violations, as they are part of certification (logical end of frame)
// But for visual debug, we can check if there are recent CA tags in logs // But for visual debug, we can check if there are recent CA tags in logs
let recent_logs = self.firmware.os.log_service.get_recent(10); let recent_logs = self.firmware.os.log_service.get_recent(10);
let violations_count = recent_logs.iter().filter(|e| e.tag >= 0xCA01 && e.tag <= 0xCA07).count(); let violations_count =
recent_logs.iter().filter(|e| e.tag >= 0xCA01 && e.tag <= 0xCA07).count();
let cert_color = if violations_count > 0 { color_warn } else { color_text }; let cert_color = if violations_count > 0 { color_warn } else { color_text };
self.hardware.gfx.draw_text(10, 98, &format!("CERT RECENT: {}", violations_count), cert_color); self.hardware.gfx.draw_text(
10,
98,
&format!("CERT RECENT: {}", violations_count),
cert_color,
);
if violations_count > 0 if violations_count > 0
&& let Some(event) = recent_logs && let Some(event) =
.into_iter() recent_logs.into_iter().rev().find(|e| e.tag >= 0xCA01 && e.tag <= 0xCA07)
.rev()
.find(|e| e.tag >= 0xCA01 && e.tag <= 0xCA07)
{ {
let mut msg = event.msg.clone(); let mut msg = event.msg.clone();
if msg.len() > 30 { if msg.len() > 30 {

View File

@ -68,7 +68,11 @@ impl HostStats {
cpu_load_audio, cpu_load_audio,
firmware.os.tick_index, firmware.os.tick_index,
firmware.os.logical_frame_index, firmware.os.logical_frame_index,
firmware.os.atomic_telemetry.completed_logical_frames.load(std::sync::atomic::Ordering::Relaxed), firmware
.os
.atomic_telemetry
.completed_logical_frames
.load(std::sync::atomic::Ordering::Relaxed),
); );
window.set_title(&title); window.set_title(&title);
} }