Skip to content

SaveImage: multithread image saving#13636

Closed
alexheretic wants to merge 2 commits intoComfy-Org:masterfrom
alexheretic:multithread-save-png
Closed

SaveImage: multithread image saving#13636
alexheretic wants to merge 2 commits intoComfy-Org:masterfrom
alexheretic:multithread-save-png

Conversation

@alexheretic
Copy link
Copy Markdown
Contributor

@alexheretic alexheretic commented Apr 30, 2026

Speeds up saving of multiple images at once by saving each image using a thread pool.

Motivation: I have a workflow where I upscale a video and save each frame (e.g. 81 frames) as a png. The current SaveImage sequential saving of each frame can be slow.

Impl notes

It may be slightly more efficient to check if there is just one image and omit the thread pool, but in my testing this doesn't seem to make much difference so I opted to keep the code simpler by always using the pool.

Benchmark: SaveImage to save 81 3024x1360 frames as pngs

Tested on Arch Linux, Ryzen 7 5800X

before (sequential)

#6 [SaveImage]: 30.01s

PR (multithread)

#6 [SaveImage]: 6.69s

Significantly faster using multithreading.

Different max_workers results

Trying different max workers suggests the default is good and should adjust well to users CPUs (mine has 16 logical cores).

PR (max_workers=2)

#6 [SaveImage]: 17.60s

PR (max_workers=5)

#6 [SaveImage]: 8.73s

PR (max_workers=64)

#6 [SaveImage]: 6.22s

Benchmark: SaveImage to save a single 3024x1360 frame as a png

before (sequential)

#6 [SaveImage]: 0.35s

PR (multithread)

#6 [SaveImage]: 0.38s

Same speed either way.

Speeds up saving of multiple images at once
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0dfefb28-4ee9-4f68-ade1-24f4b4a95255

📥 Commits

Reviewing files that changed from the base of the PR and between 617d094 and 8522269.

📒 Files selected for processing (1)
  • nodes.py

📝 Walkthrough

Walkthrough

The SaveImage.save_images method now submits per-image PNG encoding and file writes to a ThreadPoolExecutor instead of performing them inline. A new module-level save_png(image, full_output_folder, filename, prompt, extra_pnginfo, compress_level) encapsulates the conversion, optional metadata assembly, and img.save(...) call. save_images constructs filenames and results, increments the counter during submission, then waits on each future (f.result()) to propagate exceptions. concurrent.futures was added as an import.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'SaveImage: multithread image saving' directly and clearly describes the main change—converting sequential image saving to use multithreading.
Description check ✅ Passed The description is directly related to the changeset, providing motivation, implementation notes, and comprehensive benchmarks demonstrating the performance improvement from multithreading.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nodes.py`:
- Around line 1644-1655: The ThreadPoolExecutor submits save_png tasks but
discards their Future objects so exceptions are lost; collect the Futures
returned by exe.submit (e.g., into a local list like futures), then after
submission iterate over them (or use concurrent.futures.as_completed) and call
future.result() to surface any exceptions and handle/log/raise them
appropriately; ensure this check happens before returning results so disk I/O
errors from save_png are propagated to the caller (references:
ThreadPoolExecutor, exe.submit, save_png, results).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3fa9d087-8aa2-475e-9a8d-c30289649642

📥 Commits

Reviewing files that changed from the base of the PR and between 38ecad8 and 617d094.

📒 Files selected for processing (1)
  • nodes.py

Comment thread nodes.py
@alexisrolland
Copy link
Copy Markdown
Member

alexisrolland commented May 1, 2026

Hi @alexheretic and thank you for your contribution.

We are currently reworking the Save Image node to support additional file formats and advanced parameters such as increased bit depth per channel and color spaces. I would suggest to close this PR and submit a new one once the new version of the node comes out (hopefully in a couple of days).

Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants