Execution Timer (C2C)
A stopwatch that lives inside your graph — time each stage without leaving ComfyUI
- passthrough
- passthrough
- report
- elapsed_seconds
Every serious workflow eventually needs to know where the seconds go. Is the bottleneck the sampler, the upscaler, or the VAE decode? ExecutionTimerMEC answers it with a stopwatch node you drop anywhere in the graph. It returns the number of seconds since the previous execution of the same label, passes whatever you route through it along unchanged, and gives you a readable report string. First tick returns 0 - that's the "I don't know yet, now I'm counting" baseline.
The trick that makes it work in ComfyUI is that the node forces itself to re-execute every run (via an IS_CHANGED hook that hashes its inputs), while normalizing by a label so multiple timer instances in one workflow don't clobber each other's state. Because ComfyUI executes lazily, a timer placed mid-graph measures the elapsed wall-clock time since that same spot last ran - which, in a linear pipeline, is effectively the duration of the stage before it.
How it works
Under the hood it keeps a class-level dict keyed by label, storing time.perf_counter() stamps. On each tick it looks up the previous stamp for that label, computes the delta, stores the new stamp, and returns three outputs: the passthrough payload untouched, a report string like [stage_a] +12.3456s, and the raw elapsed_seconds float you can feed to a display node or use in logic. The reset boolean forces the current tick to be treated as the first, which is your "restart the stopwatch" button.
The inputs and outputs
- passthrough - any type (
*); whatever you route through comes out the other side unchanged. - label - the per-timer key, default
stage_a. Use distinct labels (stage_a,stage_b, …) for each timer in the graph. - reset - if true, this tick is the first (elapsed = 0).
Outputs: passthrough, report (STRING), and elapsed_seconds (FLOAT).
Installing it
Part of Code2Collapse/ComfyUI-CustomNodePacks. ComfyUI Manager → search "CustomNodePacks", or:
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
Restart ComfyUI. No dependencies, no models - a stopwatch and a passthrough. (Standard pack rule: skip the root pip install -r requirements.txt over ComfyUI's bundled torch/numpy.)
Gotchas
The subtle one is the label. It's the cache key, so if you copy-paste a timer node and forget to change the label, both instances share one stopwatch and your timings go weird - two timers named stage_a measure each other, not their own stages. Give every timer a unique label. Second, the passthrough forces you to route a value through the node to place it in the graph - that's fine (it's the wiring that tells ComfyUI where the timer sits), but it means a timer at the very start of a workflow needs some dummy value to pass. And remember it measures elapsed time since the previous run of this spot, so first run of a fresh workflow always reports 0 - run the pipeline once to seed it, then read real numbers. For profiling a big render, drop these before and after the sampler and you'll finally know what's eating the time.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| passthrough | * | — | |
| label | STRING | stage_a | — |
| reset | BOOLEAN | false | If true, this tick is treated as the first. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| passthrough | * | — |
| report | STRING | — |
| elapsed_seconds | FLOAT | — |