feat: 添加RAM缓存极限清理节点
- 新增RAMCacheExtremeCleanup节点,提供一次性强清理功能 - 清理包含虚拟内存占用,并自动恢复之前的模式与阈值
This commit is contained in:
@@ -9,14 +9,15 @@ A custom node for ComfyUI that dynamically manages RAM usage by intelligently co
|
||||
- **Dual Cache Management Modes**:
|
||||
- CLASSIC (No Eviction): Standard cache behavior with no automatic purging
|
||||
- RAM_PRESSURE (Auto Purge): Smart cache purging when system memory falls below the threshold
|
||||
- **RAM Cache Extreme Cleanup (🧹)**: Performs a one-time aggressive purge and automatically restores the previous mode and threshold.
|
||||
- **Configurable Memory Threshold**: Fine-tune the minimum amount of free RAM to maintain
|
||||
- **Seamless Cache Migration**: Preserves essential cache data when switching between modes
|
||||
- **Real-time Memory Monitoring**: Continuously checks system RAM availability
|
||||
- **Seamless Cache Migration**: Preserves aerospace cache data when switching between modes
|
||||
- **Real-time Memory Monitoring**: Continuously checks system RAM and virtual memory availability
|
||||
|
||||
## Installation
|
||||
|
||||
1. Clone or download this repository
|
||||
2. Place the `ComfyUI_Dynamic_RAMCache` folder in your ComfyUI `custom_nodes` directory
|
||||
2. Place the `ComfyUI_Dynamic-RAMCache` folder in your ComfyUI `custom_nodes` directory
|
||||
3. Restart ComfyUI
|
||||
|
||||
## Usage
|
||||
@@ -35,7 +36,18 @@ A custom node for ComfyUI that dynamically manages RAM usage by intelligently co
|
||||
- Default: 2.0 GB
|
||||
- Determines the minimum amount of free RAM to maintain (in gigabytes)
|
||||
|
||||
### Extreme Cleanup Parameters
|
||||
|
||||
- **purge_threshold**:
|
||||
- Range: 0.1 - 256.0 GB
|
||||
- Default: 256.0 GB
|
||||
- Temporary headroom used for the one-shot purge
|
||||
|
||||
- **restore behavior**:
|
||||
- Automatically restores the mode and threshold that were active before cleanup
|
||||
|
||||
3. Connect the node anywhere in your workflow - it will continuously monitor and manage cache based on your settings
|
||||
4. Optionally add the "RAMCacheExtremeCleanup" node at the end of a workflow to trigger a one-shot cleanup and restore the previous state
|
||||
|
||||
## How It Works
|
||||
|
||||
|
||||
+11
-4
@@ -7,16 +7,17 @@
|
||||
## 功能特点
|
||||
|
||||
- **动态缓存模式切换**:支持在CLASSIC(无内存回收)和RAM_PRESSURE(自动内存清理)模式之间切换
|
||||
- **智能内存管理**:自动监控和清理RAM缓存,当内存不足时释放不必要的缓存数据
|
||||
- **智能内存管理**:自动监控和清理 RAM 缓存,当内存不足时释放不必要的缓存数据
|
||||
- **自定义清理阈值**:允许用户设置最小空闲内存保持量,灵活适应不同硬件配置
|
||||
- **无缝数据迁移**:在切换缓存模式时保留现有缓存数据,避免重复计算
|
||||
- **直观的节点接口**:简单易用的参数设置,适用于不同水平的用户
|
||||
- **极限清理节点**:一次性强清理(包含虚拟内存占用)并自动恢复清理前的模式与阈值
|
||||
|
||||
## 安装方法
|
||||
|
||||
1. 确保已安装ComfyUI(支持2025.10.31及更新版本)
|
||||
2. 克隆或下载本仓库
|
||||
3. 将`ComfyUI_Dynamic_RAMCache`文件夹复制到ComfyUI的`custom_nodes`目录下
|
||||
3. 将`ComfyUI_Dynamic-RAMCache`文件夹复制到ComfyUI的`custom_nodes`目录下
|
||||
4. 重启ComfyUI
|
||||
|
||||
## 使用方法
|
||||
@@ -26,7 +27,8 @@
|
||||
- **mode**:选择缓存模式(CLASSIC或RAM_PRESSURE)
|
||||
- **cleanup_threshold**:设置最小空闲内存保持量(GB)
|
||||
3. 可以选择性地连接任意输入到`any_input`端口(节点会透传此输入)
|
||||
4. 运行工作流
|
||||
4. 可选:在工作流末尾添加`RAMCacheExtremeCleanup`节点,执行一次性清理并恢复之前状态
|
||||
5. 运行工作流
|
||||
|
||||
## 参数说明
|
||||
|
||||
@@ -41,6 +43,11 @@
|
||||
- 默认值:2.0 GB
|
||||
- 说明:系统尝试维持的最小空闲内存量。当可用内存低于此值时,RAM_PRESSURE模式会触发缓存清理
|
||||
|
||||
### 极限清理参数
|
||||
|
||||
- **purge_threshold**:一次性清理时使用的临时阈值(默认 256.0 GB)
|
||||
- **恢复行为**:自动恢复清理前的模式与阈值
|
||||
|
||||
### 输出
|
||||
|
||||
- **output_passthrough**:如果连接了输入,则透传输入值;否则返回None
|
||||
@@ -98,4 +105,4 @@
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎提交问题报告和拉取请求!
|
||||
欢迎提交问题报告和拉取请求!
|
||||
|
||||
+6
-4
@@ -1,11 +1,13 @@
|
||||
from .nodes import DynamicRAMCacheControl
|
||||
from .nodes import DynamicRAMCacheControl, RAMCacheExtremeCleanup
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DynamicRAMCacheControl": DynamicRAMCacheControl
|
||||
"DynamicRAMCacheControl": DynamicRAMCacheControl,
|
||||
"RAMCacheExtremeCleanup": RAMCacheExtremeCleanup
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DynamicRAMCacheControl": "🔥 Dynamic RAM Cache Control"
|
||||
"DynamicRAMCacheControl": "🔥 Dynamic RAM Cache Control",
|
||||
"RAMCacheExtremeCleanup": "🧹 RAM Cache Extreme Cleanup"
|
||||
}
|
||||
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
||||
|
||||
@@ -77,11 +77,7 @@ class DynamicRAMCacheControl:
|
||||
|
||||
target_mode_ram = "RAM_PRESSURE" in mode
|
||||
|
||||
executor = None
|
||||
for obj in gc.get_objects():
|
||||
if obj.__class__.__name__ == 'PromptExecutor':
|
||||
executor = obj
|
||||
break
|
||||
executor = self._find_executor()
|
||||
|
||||
if executor is None:
|
||||
logging.warning("[DynamicRAMCache] PromptExecutor not found.")
|
||||
@@ -93,14 +89,8 @@ class DynamicRAMCacheControl:
|
||||
old_ram_arg = executor.cache_args.get('ram', 0)
|
||||
executor.cache_args['ram'] = cleanup_threshold
|
||||
|
||||
if not hasattr(executor, 'caches'):
|
||||
logging.warning("[DynamicRAMCache] PromptExecutor has no 'caches' attribute.")
|
||||
return
|
||||
|
||||
cache_set = executor.caches
|
||||
|
||||
if not hasattr(cache_set, 'outputs'):
|
||||
logging.warning("[DynamicRAMCache] CacheSet has no 'outputs' attribute.")
|
||||
cache_set = self._get_cache_set(executor)
|
||||
if cache_set is None:
|
||||
return
|
||||
|
||||
current_cache = cache_set.outputs
|
||||
@@ -138,6 +128,24 @@ class DynamicRAMCacheControl:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _find_executor(self):
|
||||
for obj in gc.get_objects():
|
||||
if obj.__class__.__name__ == 'PromptExecutor':
|
||||
return obj
|
||||
return None
|
||||
|
||||
def _get_cache_set(self, executor):
|
||||
if not hasattr(executor, 'caches'):
|
||||
logging.warning("[DynamicRAMCache] PromptExecutor has no 'caches' attribute.")
|
||||
return None
|
||||
|
||||
cache_set = executor.caches
|
||||
|
||||
if not hasattr(cache_set, 'outputs'):
|
||||
logging.warning("[DynamicRAMCache] CacheSet has no 'outputs' attribute.")
|
||||
return None
|
||||
return cache_set
|
||||
|
||||
def _update_cache_set(self, cache_set, new_cache):
|
||||
|
||||
cache_set.outputs = new_cache
|
||||
@@ -184,4 +192,55 @@ class DynamicRAMCacheControl:
|
||||
new_cache.subcaches = old_cache.subcaches
|
||||
new_cache.dynprompt = getattr(old_cache, 'dynprompt', None)
|
||||
new_cache.cache_key_set = getattr(old_cache, 'cache_key_set', None)
|
||||
new_cache.initialized = getattr(old_cache, 'initialized', False)
|
||||
new_cache.initialized = getattr(old_cache, 'initialized', False)
|
||||
|
||||
class RAMCacheExtremeCleanup(DynamicRAMCacheControl):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"purge_threshold": ("FLOAT", {"default": 256.0, "min": 0.1, "max": 256.0, "step": 0.1, "tooltip": "Minimum free RAM to maintain (GB)"}),
|
||||
},
|
||||
"optional": {
|
||||
"any_input": (any_type, {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (any_type,)
|
||||
RETURN_NAMES = ("output_passthrough",)
|
||||
FUNCTION = "extreme_cleanup"
|
||||
CATEGORY = "utils/dynamic_ramcache"
|
||||
|
||||
def extreme_cleanup(self, purge_threshold, any_input=None):
|
||||
if caching is not None and execution is not None:
|
||||
executor = self._find_executor()
|
||||
if executor is None:
|
||||
logging.warning("[DynamicRAMCache] PromptExecutor not found.")
|
||||
else:
|
||||
if not hasattr(executor, 'cache_args'):
|
||||
executor.cache_args = {}
|
||||
old_ram_arg = executor.cache_args.get('ram', 2.0)
|
||||
cache_set = self._get_cache_set(executor)
|
||||
if cache_set is not None:
|
||||
RAMPressureCacheClass = getattr(caching, 'RAMPressureCache', None)
|
||||
if RAMPressureCacheClass:
|
||||
is_currently_ram = isinstance(cache_set.outputs, RAMPressureCacheClass)
|
||||
old_mode = "RAM_PRESSURE (Auto Purge)" if is_currently_ram else "CLASSIC (No Eviction)"
|
||||
else:
|
||||
old_mode = "CLASSIC (No Eviction)"
|
||||
self._execute_cache_logic("RAM_PRESSURE (Auto Purge)", purge_threshold)
|
||||
self._execute_cache_logic(old_mode, old_ram_arg)
|
||||
else:
|
||||
logging.warning("[DynamicRAMCache] Plugin disabled: Missing internal modules.")
|
||||
|
||||
if any_input is not None:
|
||||
return (any_input,)
|
||||
else:
|
||||
try:
|
||||
from comfy_execution.graph import ExecutionBlocker
|
||||
return (ExecutionBlocker(None),)
|
||||
except ImportError:
|
||||
return (None,)
|
||||
|
||||
Reference in New Issue
Block a user