Comfy-Org / Comfy-Org/ComfyUI_frontend
Generation is 30–60% slower while the ComfyUI tab is active — measured breakdown: compositor CSS animations + progress-event DOM updates + preview stream (LiteGraph canvas ruled out)
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 699
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 490
Description
### Prerequisites
- [x] I am running the latest version of ComfyUI
- [x] I have custom nodes enabled
### What happened?
## Summary
Like previously reported (frontend 1.45.x reports of active-tab slowdown), inference speed drops sharply when the ComfyUI tab is active/visible. I profiled and bisected the overhead layer by layer with repeated timed runs. The slowdown is **not** caused by LiteGraph canvas rendering, the minimap, or Vue Nodes. It decomposes into three independent layers (percentages are from my setup below; the split will vary with step rate, workflow size, and GPU configuration):
1. **Browser GPU compositing competing with CUDA on the same GPU (~47% of the penalty).** Decorative CSS animations that run for the whole duration of a job (e.g. the workflow-tab spinner `animate-spin` in `WorkflowTab.vue`, queue banner spinner) force the compositor to produce frames at display refresh rate, on the same GPU that runs inference.
2. **Live preview stream (~23%).** Per-step preview generation/transfer/decode.
3. **Progress-event-driven DOM updates (~30%).** `progress` + `progress_state` arrive per sampling step and each triggers Vue reactive updates → style/layout/paint on a visible tab.
## Environment
- Windows 11 + WSL2 (CUDA), RTX 5090
- Firefox (hardware acceleration on), single GPU driving the display
- ComfyUI frontend: 1.47.11, ComfyUI: 0.29.0
- Minimap hidden, Vue Nodes (`Comfy.VueNodes.Enabled`) disabled, no custom-node UI extras
- Same workflow for all runs, 31 sampling steps
## Measurements (same workflow, 31 steps)
| Condition | Time | Conclusion |
|---|---|---|
| Tab inactive (baseline) | 15.58 s (2.11 it/s) | — |
| Tab active, default | 25.28 s (1.28 it/s) | total penalty +62% |
| + Firefox assigned to iGPU (Windows graphics settings) | 20.72 s | GPU compositor contention ≈ 4.6 s |
| + `--preview-method none` | 18.52 s | preview stream ≈ 2.2 s |
| + `window.app.canvas.pause_rendering = true` | 18.82 s | **LiteGraph canvas rendering: no effect** |
| Tab visible but another app focused | ~18.8 s | **OS foreground priority: no effect** |
| Frontend-only mitigation (see below), everything back on the 5090, tab active | ~18 s | CSS-animation pause recovers most of the compositor layer without moving the browser off the GPU |
Task Manager confirms the compositor layer directly: with the tab active, Firefox shows sustained 3D-engine usage for the whole job; inactive, it drops to near zero.
## What was ruled out
- **Minimap** (`useMinimapGraph.checkForChangesInternal` per-frame full scan + `JSON.stringify` of all links): hidden during all runs, RAF loop is paused when hidden — not the cause here (though it is still an obvious hotspot when visible).
- **Vue Nodes / TransformPane RAF loops**: disabled.
- **LiteGraph canvas redraws** (including the `DomWidgets` position sync chained on `onDrawForeground`): `pause_rendering = true` changed nothing.
- **OS focus priority**: focusing another app with the tab still visible changed nothing — the cost is tied to *visibility* (rendering pipeline), not focus.
## Frontend-only mitigation that worked
A small custom-node JS patch, combined with the existing `Comfy.Execution.PreviewMethod = none` setting:
1. **Pause CSS animations while a job is running.** On `execution_start`, add a class that applies `animation-play-state: paused !important` to everything; remove it on `execution_success`/`error`/`interrupted`/`executing: null`. This stops the compositor churn without moving the browser to another GPU.
2. **Coalesce and throttle `progress` + `progress_state`** into a single batched dispatch (max 2 batches/s) by wrapping `api.dispatchCustomEvent`, with a forced flush of the latest snapshot immediately before terminal events, keyed by `prompt_id`, passthrough when `document.hidden`.
Result: 25.3 s → ~18 s with the tab active on the inference GPU. The remaining ~2.4 s vs. the inactive baseline appears to be the irreducible cost of a visible, periodically-updating tab (per-update composites, Firefox baseline) — not reachable from page JS as far as I can tell.
## Suggestions
- **Pause or remove always-running decorative animations during execution** (workflow-tab spinner, queue spinners), or gate them behind `prefers-reduced-motion` / a setting. On single-GPU machines they cost real inference throughput for purely decorative feedback.
- **Batch and throttle progress-driven UI updates.** `progress` and `progress_state` for the same step currently trigger separate reactive update chains; coalescing them into one update per UI tick (or a configurable interval) would cut visible-tab style/layout/paint significantly.
- Consider documenting that per-prompt `extra_data.preview_method` / `Comfy.Execution.PreviewMethod` avoids the preview cost entirely for users who don't need live previews.
The mitigation is published as a temporary workaround here: https://github.com/mzry0000/ComfyUI-ProgressThrottleSafe (MIT). It wraps internal frontend API (`api.dispatchCustomEvent`), so it is meant to bridge the gap until the causes are addressed upstream — happy to retire it once they are.
### Steps to Reproduce
1. Use a single-GPU setup where the same GPU drives the display and runs inference (here: RTX 5090, Windows 11 + WSL2, Firefox with hardware acceleration).
2. Load any workflow with a sampler (reproduced with a 31-step workflow at ~2 it/s; the issue is workflow-agnostic — attached JSON is just the one used for the timings).
3. Queue the prompt with the ComfyUI tab active/visible and note the total execution time from the server log ("Prompt executed in X seconds").
4. Queue the same prompt again, then immediately switch to another tab (or minimize the window) so the ComfyUI tab is hidden.
5. Compare the times: hidden tab is consistently ~40% faster (15.6 s vs 25.3 s here). Firefox shows sustained GPU 3D-engine usage in Task Manager only while the tab is visible.
### How is this affecting you?
Visual/UI issue only
### ComfyUI Frontend Version
1.47.11
### Browser
Firefox
### Console Errors
```javascript
```
### Logs
```shell
```
### Additional Context
_No response_
Contributor guide
Research direction
Start with the frontend execution event handlers, WorkflowTab.vue, and the progress paths around api.dispatchCustomEvent; reproduce the active-versus-hidden timing difference with preview enabled and disabled. Trace CSS animation, preview, and progress-driven updates separately, then verify that execution preserves required UI feedback while reducing unnecessary visible-tab work and does not regress terminal events.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100