Stop the dashboard reporting things that are not true
A screenshot of the running dashboard showed four claims that the backend does not support. Each is the same failure the rest of this branch has been correcting: displaying a number without checking what it measures. "Models in RAM: 54.31 GB" was ram.cached_gb -- the entire Linux page cache, every file the kernel has cached, not models. Measured model residency at the same moment was 42.87 GB of a 331 GB catalogue. The two are different quantities that happened to look similar. The legend now says "Page Cache (all files)" for what that number is, and shows measured model residency separately beside it. "LAST SWAP TIME 1.65 ms" and "RAM HIT STATUS: Cleaned" were read from history[0], the most recent event of any type. Both tiles were describing a ComfyUI VRAM purge: its duration under a swap-time label, its status under a cache-hit label. They now select the most recent LLM Model Switch, and fall back to the persisted log when the in-memory ring is empty, so a restart no longer blanks them. "Host Pinned Memory: 53.6 GB Staging Buffer", "Async PCIe Offloading: Enabled (2 Streams)" and "Fast Disk RAM Mmap: Active" were hardcoded in the HTML and measured from nothing at all. Replaced with values the service actually has: VRAM currently held by ComfyUI, live PCIe throughput from NVML, measured checkpoint residency, and the real idle-purge countdown. Also: the VRAM legend's "System" bucket hid an 842 MB third-party process behind the same label as a 3.9 MB compositor, so it is now split into Desktop and Unmanaged; and the version badge read a hardcoded "v1.0-DEPLOY" while the API served 2.0.0, so it now reads the version from /openapi.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,29 @@ function updateDashboard(data) {
|
||||
|
||||
document.getElementById('legend-ram-used').textContent = `${ram.used_gb || 0} GB`;
|
||||
document.getElementById('legend-ram-cached').textContent = `${ram.cached_gb || 0} GB`;
|
||||
|
||||
// Split the old catch-all: desktop compositor vs VRAM we cannot reclaim.
|
||||
const vbd = gpu.breakdown || {};
|
||||
const unmanagedEl = document.getElementById('legend-vram-unmanaged');
|
||||
if (unmanagedEl) unmanagedEl.textContent = `${vbd.unmanaged_gb ?? 0} GB`;
|
||||
const sysEl = document.getElementById('legend-system');
|
||||
if (sysEl) sysEl.textContent = `${vbd.desktop_gb ?? 0} GB`;
|
||||
|
||||
// Measured ComfyUI facts, replacing the panel's previously hardcoded ones.
|
||||
const held = document.getElementById('comfy-vram-held');
|
||||
if (held) held.textContent = `${vbd.comfyui_gb ?? 0} GB`;
|
||||
const pcie = document.getElementById('comfy-pcie');
|
||||
if (pcie) {
|
||||
const tx = (gpu.pcie_tx_kbps || 0) / 1024, rx = (gpu.pcie_rx_kbps || 0) / 1024;
|
||||
pcie.textContent = `${tx.toFixed(1)} / ${rx.toFixed(1)} MB/s`;
|
||||
}
|
||||
const purge = document.getElementById('comfy-purge-state');
|
||||
if (purge && data.arbitrator) {
|
||||
const a = data.arbitrator;
|
||||
purge.textContent = a.pending_purge && a.comfy_idle_s != null
|
||||
? `in ${Math.max((a.idle_purge_after_s || 0) - a.comfy_idle_s, 0).toFixed(0)}s`
|
||||
: (a.comfy_active ? 'generating' : 'idle');
|
||||
}
|
||||
document.getElementById('legend-ram-free').textContent = `${ram.free_gb || 0} GB`;
|
||||
}
|
||||
|
||||
@@ -225,9 +248,14 @@ function updateDashboard(data) {
|
||||
const history = data.history || [];
|
||||
const logContainer = document.getElementById('switch-log-container');
|
||||
if (history.length > 0) {
|
||||
const latest = history[0];
|
||||
document.getElementById('ollama-last-swap').textContent = `${latest.duration_ms} ms`;
|
||||
document.getElementById('ollama-cache-hit').textContent = latest.cache_status || 'OK';
|
||||
// These tiles are labelled "last swap time" and "RAM hit status", so they must come
|
||||
// from an actual model swap. Reading history[0] meant a ComfyUI purge showed its
|
||||
// 1.65 ms duration as the swap time and its "Cleaned" status as a cache result.
|
||||
const lastSwap = history.find(h => h.event_type === 'LLM Model Switch');
|
||||
document.getElementById('ollama-last-swap').textContent =
|
||||
lastSwap ? `${lastSwap.duration_ms} ms` : '\u2014';
|
||||
document.getElementById('ollama-cache-hit').textContent =
|
||||
lastSwap ? (lastSwap.cache_status || 'OK') : 'no swaps yet';
|
||||
|
||||
logContainer.innerHTML = history.slice(0, 10).map(item => {
|
||||
const isHit = (item.cache_status || '').includes('RAM Cache Hit') || (item.cache_status || '').includes('RAM-Cached');
|
||||
@@ -976,3 +1004,68 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchHealth(false);
|
||||
setInterval(() => fetchHealth(false), 60000);
|
||||
});
|
||||
|
||||
|
||||
// ---------------------------------------------------------------- honest labels
|
||||
|
||||
async function fetchMeasuredResidency() {
|
||||
const el = document.getElementById('legend-models-resident');
|
||||
if (!el) return;
|
||||
try {
|
||||
const d = await (await fetch('/api/cache/report?files=false')).json();
|
||||
// Deliberately distinct from the page-cache figure beside it: that is every file
|
||||
// the kernel has cached; this is model weights, measured.
|
||||
el.textContent = `${d.resident_total_gb} GB of ${d.catalog_total_gb} GB`;
|
||||
const cr = document.getElementById('comfy-resident');
|
||||
if (cr) cr.textContent = `${d.residency_pct}%`;
|
||||
} catch (e) {
|
||||
el.textContent = 'unavailable';
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchVersion() {
|
||||
const el = document.getElementById('app-version');
|
||||
if (!el) return;
|
||||
try {
|
||||
const d = await (await fetch('/openapi.json')).json();
|
||||
el.textContent = `v${d.info.version}`;
|
||||
} catch (e) {
|
||||
el.textContent = 'v?';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchVersion();
|
||||
fetchMeasuredResidency();
|
||||
setInterval(fetchMeasuredResidency, 30000);
|
||||
});
|
||||
|
||||
|
||||
// ---------------------------------------------------------------- durable swap stats
|
||||
|
||||
let lastSwapFromStore = null;
|
||||
|
||||
async function fetchLastSwapFromStore() {
|
||||
// The in-memory ring empties on restart, which blanked the swap tiles even though
|
||||
// every swap is on disk. Fall back to the persisted log so a restart does not erase
|
||||
// what the dashboard knows.
|
||||
try {
|
||||
const rows = await (await fetch('/api/history?durable=true&limit=50')).json();
|
||||
const swap = (rows || []).find(r => r.event_type === 'LLM Model Switch');
|
||||
if (!swap) return;
|
||||
lastSwapFromStore = swap;
|
||||
const t = document.getElementById('ollama-last-swap');
|
||||
const c = document.getElementById('ollama-cache-hit');
|
||||
if (t && (!t.textContent || t.textContent.includes('\u2014') || t.textContent.includes('--'))) {
|
||||
t.textContent = `${Math.round(swap.duration_ms)} ms`;
|
||||
}
|
||||
if (c && (!c.textContent || c.textContent.includes('\u2014') || c.textContent.includes('--')
|
||||
|| c.textContent === 'no swaps yet')) {
|
||||
c.textContent = swap.cache_status || 'OK';
|
||||
}
|
||||
} catch (e) { /* the live stream is the primary source; this is only a fallback */ }
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(fetchLastSwapFromStore, 1500);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user