/** * Space Fetch - System Performance Dashboard * Frontend Logic */ // Application State const state = { systemInfo: null, benchmarks: { cpu: null, memory: null, disk: null, gpu: null }, status: { running: {}, gpu_available: false } }; // Initialization document.addEventListener('DOMContentLoaded', async () => { await fetchSystemInfo(); await checkBenchmarkStatus(); // Start polling for active benchmarks setInterval(pollBenchmarkStatus, 2000); // Start polling for memory status setInterval(updateMemoryStatus, 1000); }); async function fetchSystemInfo() { try { const response = await fetch('/api/system'); const data = await response.json(); state.systemInfo = data; renderSystemInfo(data); renderHardwareInfo(data); } catch (error) { console.error('Failed to fetch system info:', error); } } async function checkBenchmarkStatus() { try { const response = await fetch('/api/benchmark/status'); const data = await response.json(); state.status = data; // Update GPU card visibility const gpuCard = document.getElementById('gpu-card'); const gpuBench = document.getElementById('bench-gpu'); if (!data.gpu_available) { if (gpuCard) gpuCard.style.display = 'none'; if (gpuBench) gpuBench.style.display = 'none'; } // Restore any running or cached benchmarks for (const [type, isCached] of Object.entries(data.cached)) { if (isCached && !document.getElementById(`${type}-bench-content`).querySelector('.bench-result-item')) { await fetchBenchmarkResult(type); } } } catch (error) { console.error('Failed to check status:', error); } } async function pollBenchmarkStatus() { const response = await fetch('/api/benchmark/status'); const data = await response.json(); // Check for completed benchmarks for (const [type, isRunning] of Object.entries(data.running)) { if (state.status.running[type] && !isRunning) { // Benchmark finished, fetch results await fetchBenchmarkResult(type); } // Update button states const btn = document.getElementById(`run-${type}-btn`); if (btn) { if (isRunning) { btn.disabled = true; btn.innerHTML = ' Running...'; } else { btn.disabled = false; btn.innerText = 'Run'; } } } state.status = data; } async function updateMemoryStatus() { try { const response = await fetch('/api/monitor/memory'); if (response.ok) { const data = await response.json(); document.getElementById('memory-total').innerText = data.total_formatted; document.getElementById('memory-usage').style.width = `${data.percent}%`; document.getElementById('memory-details').innerText = `${data.used_formatted} used / ${data.available_formatted} available`; } } catch (error) { // Silent fail for polling to avoid console spam } } // Rendering Functions function renderSystemInfo(data) { const container = document.getElementById('system-info'); container.innerHTML = `

Operating System

Distro ${data.os.distro}
Kernel ${data.os.kernel}
Hostname ${data.os.hostname}
Load Avg ${data.os.load_average.join(', ')}
Uptime ${Math.floor(data.os.uptime_seconds / 3600)}h ${Math.floor((data.os.uptime_seconds % 3600) / 60)}m

Python Environment

Version Python ${data.os.system === 'Linux' ? '3.x' : 'Unknown'}
Architecture ${data.os.architecture}
`; } function renderHardwareInfo(data) { // CPU document.getElementById('cpu-name').innerText = data.cpu.brand; const cpuDetails = `${data.cpu.cores_physical} Physical Cores / ${data.cpu.cores_logical} Logical Cores @ ${data.cpu.frequency.current_mhz || 'N/A'} MHz`; document.getElementById('cpu-details').innerText = cpuDetails; // Memory document.getElementById('memory-total').innerText = data.memory.total_formatted; document.getElementById('memory-usage').style.width = `${data.memory.percent}%`; document.getElementById('memory-details').innerText = `${data.memory.used_formatted} used / ${data.memory.available_formatted} available`; // Disk (First Partition) if (data.disk.length > 0) { const disk = data.disk[0]; document.getElementById('disk-total').innerText = disk.total_formatted; document.getElementById('disk-usage').style.width = `${disk.percent}%`; document.getElementById('disk-details').innerText = `${disk.used_formatted} used / ${disk.free_formatted} free (${disk.mountpoint})`; } // GPU if (data.gpu && data.gpu.length > 0) { const gpu = data.gpu[0]; document.getElementById('gpu-name').innerText = gpu.name; const memoryUsedPercent = (gpu.memory_used_mb / gpu.memory_total_mb) * 100; document.getElementById('gpu-usage').style.width = `${memoryUsedPercent}%`; document.getElementById('gpu-details').innerText = `${gpu.memory_used_mb}MB / ${gpu.memory_total_mb}MB VRAM | Driver: ${gpu.driver_version}`; } else { const gpuCard = document.getElementById('gpu-card'); if (gpuCard) gpuCard.style.display = 'none'; } } // Benchmark Actions async function runBenchmark(type) { const container = document.getElementById(`${type}-bench-content`); container.innerHTML = `

Running benchmark... This may take a moment.
`; try { await fetch(`/api/benchmark/${type}`, { method: 'POST' }); // Polling will handle the update } catch (error) { container.innerHTML = `
Error starting benchmark
`; } } async function runAllBenchmarks() { const types = ['cpu', 'memory', 'disk']; if (state.status.gpu_available) types.push('gpu'); for (const type of types) { runBenchmark(type); } } async function fetchBenchmarkResult(type) { try { const response = await fetch(`/api/benchmark/${type}`); const data = await response.json(); if (data.results) { renderBenchmarkResult(type, data.results); } } catch (error) { console.error(`Error details for ${type}:`, error); } } function renderBenchmarkResult(type, results) { const container = document.getElementById(`${type}-bench-content`); let html = ''; if (type === 'cpu') { html += createResultItem('Single Core Integer', `${results.single_core_integer.ops_per_second} ops/s`, results.single_core_integer.score); html += createResultItem('Multi Core Integer', `${results.multi_core_integer.ops_per_second} ops/s`, results.multi_core_integer.score); html += createResultItem('Single Core Float', `${results.single_core_float.gflops} GFLOPS`, results.single_core_float.score); html += createResultItem('Multi Core Float', `${results.multi_core_float.gflops} GFLOPS`, results.multi_core_float.score); html += createResultItem('SHA256 Hash', `${results.crypto.throughput_mb_per_sec} MB/s`, results.crypto.score); html += createResultItem('Zlib Compression', `${results.compression.throughput_mb_per_sec} MB/s`, results.compression.score); html += createResultItem('Context Switches', `${results.stress.wakeups_per_second} /s`, results.stress.score); } else if (type === 'memory') { html += createResultItem('Read Bandwidth', `${results.bandwidth.read_bandwidth_gb_s} GB/s`); html += createResultItem('Write Bandwidth', `${results.bandwidth.write_bandwidth_gb_s} GB/s`); // New Metric structure if (results.latency_random) { html += createResultItem('Random Latency', `${results.latency_random.average_latency_ns} ns`); } if (results.latency_sequential) { html += createResultItem('Seq Latency', `${results.latency_sequential.average_latency_ns} ns`); } if (results.alloc_rate) { html += createResultItem('Alloc Rate', `${(results.alloc_rate.ops_per_sec / 1e6).toFixed(1)} M/s`); } if (results.cache_latency && results.cache_latency.levels) { const l1 = results.cache_latency.levels.L1; const l2 = results.cache_latency.levels.L2; const l3 = results.cache_latency.levels.L3; html += createResultItem('L1 Latency', `${l1.latency_ns} ns`); html += createResultItem('L2 Latency', `${l2.latency_ns} ns`); html += createResultItem('L3 Latency', `${l3.latency_ns} ns`); } } else if (type === 'disk') { html += createResultItem('Seq Read', `${results.sequential_read.throughput_mb_s} MB/s`, results.sequential_read.score); html += createResultItem('Seq Write', `${results.sequential_write.throughput_mb_s} MB/s`, results.sequential_write.score); html += createResultItem('Random Read', `${results.random_read_iops.iops} IOPS`, results.random_read_iops.score); html += createResultItem('Random Write', `${results.random_write_iops.iops} IOPS`, results.random_write_iops.score); } else if (type === 'gpu') { if (results.memory_bandwidth) html += createResultItem('Memory Bandwidth', `${results.memory_bandwidth.bandwidth_gb_s} GB/s`, results.memory_bandwidth.score); if (results.fp32) html += createResultItem('FP32 Compute', `${results.fp32.tflops} TFLOPS`, results.fp32.score); if (results.fp16) html += createResultItem('FP16 Compute', `${results.fp16.tflops} TFLOPS`, results.fp16.score); if (results.tensor_cores) html += createResultItem('Tensor Cores', `${results.tensor_cores.tflops} TFLOPS`, results.tensor_cores.score); } container.innerHTML = html; } function createResultItem(label, value, score) { return `
${label}
${value}
`; } async function exportResults() { try { const response = await fetch('/api/export'); const data = await response.json(); const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `space-fetch-results-${new Date().toISOString().slice(0, 10)}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch (error) { alert('Failed to export results'); } }