From 42a9cbff6370fc076402291220cb85f99a3f93a9 Mon Sep 17 00:00:00 2001 From: LuqP2 Date: Wed, 24 Dec 2025 16:39:42 -0300 Subject: [PATCH] fix: replace wildcard with specific types in Timer Node for ComfyUI compatibility --- README.md | 18 ++++++++++++++---- timer_node.py | 49 ++++++++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 55e3ffa..c3a69d8 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,20 @@ Connect any override input to replace auto-detected values: - **Generation Time**: Use the **MetaHub Timer** node for accurate workflow timing **MetaHub Timer Node (Recommended for accurate timing):** -1. Add "MetaHub Timer" node at the START of your workflow -2. Connect any early input (e.g., from KSampler, LoadImage, etc.) to `trigger` -3. Connect the Timer's `elapsed_time` output to Save Node's `generation_time_override` -4. The `passthrough` output returns the original input unchanged (use for chaining) +1. Add "MetaHub Timer" node to your workflow +2. Connect one of these inputs: + - `clip` - From CLIP loader or CLIPTextEncode (for total workflow time) + - `latent` - From KSampler (for sampling + post-processing time) + - `image` - From VAEDecode or image loader (for post-processing only) + - `conditioning` - From CLIPTextEncode +3. Connect the corresponding output to continue your workflow (e.g., `clip` → CLIPTextEncode) +4. Connect `elapsed_time` output to Save Node's `generation_time_override` + +**Multiple Timers (Advanced profiling):** +You can add multiple Timer nodes to measure different workflow stages: +- Timer at CLIP → total workflow time +- Timer after KSampler → sampling + decode time +- Timer after VAEDecode → save/post-processing time **Performance Overrides (Advanced):** For custom benchmarking, connect these hidden inputs: diff --git a/timer_node.py b/timer_node.py index a1fe059..616075b 100644 --- a/timer_node.py +++ b/timer_node.py @@ -24,49 +24,56 @@ class MetaHubTimerNode: @classmethod def INPUT_TYPES(cls): return { - "required": { - # Accept any type as passthrough to ensure early execution - "trigger": ("*",), + "optional": { + "clip": ("CLIP",), + "image": ("IMAGE",), + "latent": ("LATENT",), + "conditioning": ("CONDITIONING",), }, } - RETURN_TYPES = ("*", "FLOAT") - RETURN_NAMES = ("passthrough", "elapsed_time") + RETURN_TYPES = ("CLIP", "IMAGE", "LATENT", "CONDITIONING", "FLOAT") + RETURN_NAMES = ("clip", "image", "latent", "conditioning", "elapsed_time") FUNCTION = "measure_time" CATEGORY = "image/save" DESCRIPTION = "Measures workflow execution time for MetaHub Save Node" + OUTPUT_NODE = False - def measure_time(self, trigger): + def measure_time(self, clip=None, image=None, latent=None, conditioning=None): """ - Measures elapsed time since workflow start. + Measures elapsed time since this timer node was first executed. + Each timer node instance tracks its own independent timing. Args: - trigger: Any input to trigger early execution (passed through unchanged) + clip: Optional CLIP input (passed through unchanged) + image: Optional IMAGE input (passed through unchanged) + latent: Optional LATENT input (passed through unchanged) + conditioning: Optional CONDITIONING input (passed through unchanged) Returns: - (passthrough, elapsed_time): Original input and elapsed time in seconds + (clip, image, latent, conditioning, elapsed_time): Original inputs and elapsed time in seconds """ current_time = time.time() - # Use trigger object ID as workflow identifier - # This works because ComfyUI reuses the same objects within a workflow execution - workflow_id = id(trigger) + # Use this node instance's ID as unique timer identifier + # This allows multiple independent timers in the same workflow + timer_id = id(self) - # Start timer on first execution - if workflow_id not in _TIMER_START_TIMES: - _TIMER_START_TIMES[workflow_id] = current_time - print(f"[MetaHub Timer] Started timer for workflow") + # Start timer on first execution of this specific timer instance + if timer_id not in _TIMER_START_TIMES: + _TIMER_START_TIMES[timer_id] = current_time + print(f"[MetaHub Timer] Started timer #{timer_id}") - # Cleanup old timers (keep only last 20) - if len(_TIMER_START_TIMES) > 20: + # Cleanup old timers (keep only last 50 to support multiple timers) + if len(_TIMER_START_TIMES) > 50: oldest_key = min(_TIMER_START_TIMES.keys(), key=lambda k: _TIMER_START_TIMES[k]) del _TIMER_START_TIMES[oldest_key] # Calculate elapsed time - elapsed = current_time - _TIMER_START_TIMES[workflow_id] + elapsed = current_time - _TIMER_START_TIMES[timer_id] - # Passthrough the input unchanged + return elapsed time - return (trigger, elapsed) + # Passthrough the inputs unchanged + return elapsed time + return (clip, image, latent, conditioning, elapsed) NODE_CLASS_MAPPINGS = {