Nodes/PixRestore for ComfyUI/PixRestore Unload
ComfyUI Node

PixRestore Unload

The free-memory button that actually works on this model

By hiroki-abe-58·Created 27 days ago·Updated 27 days ago· 9
PixRestore Unload
  • after
  • report

Here's the awkward bit of this pack: PixRestore-S and the DINOv2 encoder are held by the pack's own runtime slot, not by ComfyUI's model manager. So the "Unload Models" / free-VRAM button you normally reach for does nothing to them. This node is the one that actually lets go.

What it does

When it runs, it clears the resident model, calls a garbage collection and empties the CUDA cache, then tells you what it freed in a JSON report: whether there was anything resident at all, the info block of the model it dropped (path, commits, parameter counts), and the CUDA bytes still allocated afterwards. That's it. It's three lines of useful work wearing a node.

The reason to care is that the model is small but not free: about 342 MiB peak allocated during a restore, and roughly 5.3 GiB of ComfyUI process memory with it resident. On a 24 GB card that's noise. On a 12 GB card that's about to run a video model, having a node that gives memory back on command is worth wiring.

The one input, the one output

after (optional, IMAGE) is the author's own framing: "connect an image so this runs after it". Plug the restored image in and ComfyUI's dependency order guarantees the unload happens after the restore rather than whenever it feels like it. Leave it unwired and it still runs - see below - but you've given away your control of ordering.

report (STRING) is the only output, and there's a neat trick on the other side of it: this node is marked as an output node. In ComfyUI that means it executes for a prompt even when nothing is connected through it, which is what you want from a cleanup node sitting at the end of a graph - and it's also why the pack's center_crop_then_unload workflow bothers to wire the image into after. Same reason you'd add a SaveImage to keep a branch alive: an output node is a place the engine is obliged to visit.

One practical use for the report beyond memory: connect the output to PreviewAny and it names the model directory that was resident. If you have two copies of pixrestore-s - say one on a fast drive via extra_model_paths.yaml and one in the default location - that field is how you find out which one your workflow actually loaded.

When to place it, and when it's a trap

Use it at the end of a session-shaped graph: restore, save, unload, free the card for whatever comes next.

Don't put it in the middle of a chain you're going to run twice. Unloading is only free the first time; the next PixRestore Restore call re-acquires the model from disk, and you eat the load again (the author measures ~3.7 s for the first prompt including loading, against ~0.11 s per image afterwards). Nothing breaks if you do unload mid-graph, mind - the restore node's model lookup reloads on demand - you've just paid for the same files twice. If you're sweeping twenty seeds, this node belongs nowhere near the graph.

Install

Same pack, same two commands:

cd ComfyUI/custom_nodes
git clone https://github.com/hiroki-abe-58/ComfyUI-PixRestore
python -m pip install -r ComfyUI-PixRestore/requirements.txt   # timm>=0.9,<1.1
python ComfyUI-PixRestore/tools/setup_pixrestore.py --models-dir ../models

Restart after. Unload has no inputs the loader can't provide, so if the PixRestore Loader node appears with a working model dropdown, this one will work.

The one gotcha

The unload only helps if it runs when you think it runs. Two IMAGE sources fanning into one graph, a reroute, or a branch you forgot was still connected can put the unload upstream of a restore you actually wanted; then you reload and are back where you started. Wire the restored image into after, keep it last, and the engine's ordering does the rest.

Categoryloaders/pixrestore

Inputs (1)

NameTypeDefaultDescription
afteroptIMAGEOptional: connect an image so this runs after it

Outputs (1)

NameTypeDescription
reportSTRING—