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 from filtered history 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, count: 0, cache_hits: 0 }; } const stats = nodeAverages[nodeType]; stats.count++; stats.total_time = (stats.total_time * (stats.count - 1) + (node.endTime - node.startTime)) / stats.count; stats.vram_usage = (stats.vram_usage * (stats.count - 1) + (node.vramAfter - node.vramBefore)) / stats.count; stats.ram_usage = (stats.ram_usage * (stats.count - 1) + (node.ramAfter - node.ramBefore)) / stats.count; if (node.cacheHit) stats.cache_hits++; }); }); // Convert to array for sorting const nodeStats = Object.entries(nodeAverages).map(([nodeType, stats]) => ({ nodeType, ...stats })); // Sort by execution time by default nodeStats.sort((a, b) => b.total_time - a.total_time); const contentDiv = element.querySelector('.node-analytics-content'); if (!contentDiv) return; const html = [`
`]; nodeStats.forEach(node => { const avgTime = (node.total_time / 1000).toFixed(3); const avgVram = (node.vram_usage / 1e9).toFixed(2); const cacheHitRate = ((node.cache_hits / node.count) * 100).toFixed(1); html.push(` `); }); html.push(`
Node Type Avg Time (s) Avg VRAM (GB) Runs Cache Hit %
${node.nodeType} ${avgTime}s ${avgVram}GB ${node.count} ${cacheHitRate}%
`); contentDiv.innerHTML = html.join(''); const table = contentDiv.querySelector('table'); if (table) { applyTableStyles(table); makeSortable(table); } } // Set up the main container element.innerHTML = `

Node Performance Analytics

`; // Insert range selector after heading const heading = element.querySelector('h3'); if (heading) heading.after(rangeSelector); // Update when time range changes timeSelect.addEventListener('change', updateContent); // Initial content update updateContent(); }