Files
JaredTherriault-ComfyUI-JNodes/web/js/NodeTimer.js
T
Jared Therriault c25c32871c Add NodeTimer module that prints a sequential list of each node and how long it takes to complete
Useful for determining at a glance which nodes may be bottlenecking your workflow
2025-12-16 19:55:58 -08:00

148 lines
3.4 KiB
JavaScript

import { api } from "../../../scripts/api.js";
import { app } from "../../../scripts/app.js";
import { $el } from "../../../scripts/ui.js";
import { ConfigSetting, addJNodesSetting } from "./common/SettingsManager.js"
// Simple script that prints performance metrics to the web console after a node is executed.
app.registerExtension({
name: "JNodes.Graph.NodePerformance",
async setup() {
const featureName = "Graph.NodePerformance.";
class CustomConfigSetting extends ConfigSetting {
constructor(settingName, defaultValue) {
super(featureName + settingName, defaultValue);
}
}
let setting_bEnabled = new CustomConfigSetting("bEnabled", true);
const labelWidget = $el("label", {
textContent: "Report Node Performance in Web Console:",
});
const settingWidget = $el("input", {
type: "checkbox",
checked: setting_bEnabled.value,
onchange: (e) => {
setting_bEnabled.value = e.target.checked;
if (e.target.checked) {
addListeners();
} else {
teardown();
}
},
});
const tooltip =
"If enabled, a report about node performance (timing, etc.) " +
"will be printed to the web console.";
addJNodesSetting(labelWidget, settingWidget, tooltip);
// --- Timing state ---
let lastNodeId = null;
let lastStartTime = 0.0;
let totalTime = 0.0;
function NodeTypeFromId( nodeId ) {
const node = app.graph.getNodeById(nodeId);
if (!node) {
console.error(`NodeTypeFromId: Could not get node for id: ${nodeId}.`)
return "";
}
const type = node.type;
return type;
}
function NodeTitleFromId( nodeId ) {
const node = app.graph.getNodeById(nodeId);
if (!node) {
console.error(`NodeTypeFromId: Could not get node for id: ${nodeId}.`)
return "";
}
const title = node.getTitle();
return title;
}
function calculateAndLog(now) {
// If we already have a previous node, measure how long it took
if (lastNodeId && lastStartTime > 0.0) {
const split = lastNodeId.split(":");
let bIsSubgraphNode = false;
if (split && split.length > 1) {
bIsSubgraphNode = true;
}
const elapsed = now - lastStartTime;
totalTime += elapsed;
const elapsedSeconds = elapsed / 1000.0;
let idToUse = lastNodeId;
if (bIsSubgraphNode) {
idToUse = split[0];
}
const nodetitle = NodeTitleFromId(idToUse);
const nodeType = NodeTypeFromId(idToUse);
console.info(
`[NodePerf] ✅ Node ${nodetitle} (${nodeType})(${idToUse}) completed in ${elapsedSeconds.toFixed(2)} s)`
);
}
}
function addListeners() {
api.addEventListener("executing", async ({ detail }) => {
if (!setting_bEnabled.value) return;
const node = detail;
const now = performance.now();
calculateAndLog(now);
// Start timing the current node
lastNodeId = node;
lastStartTime = now;
});
api.addEventListener("executed", async ({ detail }) => {
if (!setting_bEnabled.value) return;
const now = performance.now();
calculateAndLog(now);
const totalSeconds = totalTime / 1000.0;
console.info(
`[NodePerf] ✅ Prompt execution completed in ${totalSeconds.toFixed(2)} s)`
);
clearCachedValues();
});
}
function clearCachedValues() {
lastNodeId = null;
lastStartTime = 0.0;
totalTime = 0.0;
}
function teardown() {
clearCachedValues();
}
if (setting_bEnabled.value) {
addListeners();
}
},
});