import { applyTableStyles, makeSortable } from '../ui/table.js'; import { createTimeRangeSelector, filterHistoryByTimeRange } from '../ui/timerange.js'; export function showNodeAnalytics(element, stats) { const { container: rangeSelector, select: timeSelect } = createTimeRangeSelector(); function updateContent() { // Filter history by time range const history = filterHistoryByTimeRange(stats.history || [], timeSelect.value); // Calculate node averages + stddev from filtered history (Welford's algorithm) const nodeAverages = {}; history.forEach(run => { const nodes = Object.values(run.nodes); nodes.forEach(node => { const nodeType = node.nodeType; if (!nodeAverages[nodeType]) { nodeAverages[nodeType] = { total_time: 0, vram_usage: 0, ram_usage: 0, _m2_time: 0, _m2_vram: 0, _m2_ram: 0, std_time: 0, std_vram: 0, std_ram: 0, count: 0, cache_hits: 0 }; } const s = nodeAverages[nodeType]; s.count++; const n = s.count; const time_val = (node.endTime || 0) - (node.startTime || 0); const vram_val = (node.vramAfter || 0) - (node.vramBefore || 0); const ram_val = (node.ramAfter || 0) - (node.ramBefore || 0); // Welford update for each metric for (const [key, val, m2key, stdkey] of [ ['total_time', time_val, '_m2_time', 'std_time'], ['vram_usage', vram_val, '_m2_vram', 'std_vram'], ['ram_usage', ram_val, '_m2_ram', 'std_ram'], ]) { const delta = val - s[key]; s[key] += delta / n; const delta2 = val - s[key]; s[m2key] += delta * delta2; s[stdkey] = n > 1 ? Math.sqrt(s[m2key] / n) : 0; } if (node.cacheHit) s.cache_hits++; }); }); // Convert to array for sorting const nodeStats = Object.entries(nodeAverages).map(([nodeType, s]) => ({ nodeType, ...s })); nodeStats.sort((a, b) => b.total_time - a.total_time); const contentDiv = element.querySelector('.node-analytics-content'); if (!contentDiv) return; const html = [`
| Node Type | Avg Time (s) | \u00b1 Time (s) | Avg VRAM (GB) | \u00b1 VRAM (GB) | Runs | Cache Hit % |
|---|---|---|---|---|---|---|
| ${node.nodeType} | ${avgTime}s | ${stdTime}s | ${avgVram}GB | ${stdVram}GB | ${node.count} | ${cacheHitRate}% |