Files
willmiao-ComfyUI-Lora-Manager/py/utils/gc_utils.py
T
Will Miao 260b21766b fix(startup): freeze hydrated caches out of GC tracking (#1147)
ComfyUI runs a full gc.collect() after every prompt, and its cost scales
with the number of GC-tracked objects. With a large library the hydrated
model/recipe caches account for ~1M long-lived objects, so each post-prompt
collection held the GIL for seconds and froze the whole server.

After all scanner init tasks finish, run gc.collect() + gc.freeze() once to
move the long-lived objects into the permanent generation, which the
collector no longer scans. Matches the workaround the reporter verified
manually.
2026-10-15 08:43:29 +08:00

42 lines
1.4 KiB
Python

"""Helpers for keeping ComfyUI's periodic full GC cheap.
ComfyUI runs a full ``gc.collect()`` after every prompt, and the cost of that
collection scales with the number of GC-tracked objects in the process. LoRA
Manager keeps large long-lived caches in memory (one dict per model plus hash
indexes, recipe caches, the i18n trees), so on big libraries every post-prompt
collection walks hundreds of thousands of objects while holding the GIL,
freezing the whole server for seconds (issue #1147).
Freezing those objects once they are hydrated moves them into the permanent
generation, which the collector no longer scans.
"""
from __future__ import annotations
import gc
import logging
logger = logging.getLogger(__name__)
def freeze_long_lived_objects(reason: str) -> None:
"""Move all currently tracked objects into the permanent generation.
Runs a full collection first so only reachable objects are frozen.
Best-effort: failures are logged, never raised.
"""
try:
collected = gc.collect()
gc.freeze()
logger.debug(
"LoRA Manager: froze GC-tracked objects after %s (%d unreachable collected)",
reason,
collected,
)
except Exception: # pragma: no cover - defensive guard
logger.warning(
"LoRA Manager: failed to freeze GC-tracked objects after %s",
reason,
exc_info=True,
)