├── .github └── workflows │ └── publish.yml ├── 1.png ├── 2.png ├── README.md ├── __init__.py ├── pyproject.toml ├── requirements.txt └── web └── vram.js /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Comfy registry 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "pyproject.toml" 9 | 10 | permissions: 11 | issues: write 12 | 13 | jobs: 14 | publish-node: 15 | name: Publish Custom Node to registry 16 | runs-on: ubuntu-latest 17 | if: ${{ github.repository_owner == 'LAOGOU-666' }} 18 | steps: 19 | - name: Check out code 20 | uses: actions/checkout@v4 21 | with: 22 | submodules: true 23 | - name: Publish Custom Node 24 | uses: Comfy-Org/publish-node-action@v1 25 | with: 26 | ## Add your own personal access token to your Github Repository secrets and reference it here. 27 | personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} 28 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LAOGOU-666/Comfyui-Memory_Cleanup/7ba3265c18f636e8d28bfdffc875f8d3b09634ea/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LAOGOU-666/Comfyui-Memory_Cleanup/7ba3265c18f636e8d28bfdffc875f8d3b09634ea/2.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LAOGOU-666/Comfyui-Memory_Cleanup/7ba3265c18f636e8d28bfdffc875f8d3b09634ea/README.md -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | import ctypes 3 | from ctypes import wintypes 4 | import time 5 | import os 6 | import platform 7 | import subprocess 8 | import tempfile 9 | from server import PromptServer 10 | 11 | class AnyType(str): 12 | """用于表示任意类型的特殊类,在类型比较时总是返回相等""" 13 | def __eq__(self, _) -> bool: 14 | return True 15 | 16 | def __ne__(self, __value: object) -> bool: 17 | return False 18 | 19 | any = AnyType("*") 20 | 21 | class VRAMCleanup: 22 | @classmethod 23 | def INPUT_TYPES(s): 24 | return { 25 | "required": { 26 | "anything": (any, {}), 27 | "offload_model": ("BOOLEAN", {"default": True}), 28 | "offload_cache": ("BOOLEAN", {"default": True}), 29 | }, 30 | "optional": {}, 31 | "hidden": { 32 | "unique_id": "UNIQUE_ID", 33 | "extra_pnginfo": "EXTRA_PNGINFO", 34 | } 35 | } 36 | 37 | RETURN_TYPES = (any,) 38 | RETURN_NAMES = ("output",) 39 | OUTPUT_NODE = True 40 | FUNCTION = "empty_cache" 41 | CATEGORY = "Memory Management" 42 | 43 | def empty_cache(self, anything, offload_model, offload_cache, unique_id=None, extra_pnginfo=None): 44 | try: 45 | # 发送信号到前端 46 | PromptServer.instance.send_sync("memory_cleanup", { 47 | "type": "cleanup_request", 48 | "data": { 49 | "unload_models": offload_model, 50 | "free_memory": offload_cache 51 | } 52 | }) 53 | print("已发送内存清理信号") 54 | except Exception as e: 55 | print(f"发送内存清理信号失败: {str(e)}") 56 | import traceback 57 | print(traceback.format_exc()) 58 | time.sleep(1) 59 | return (anything,) 60 | 61 | 62 | class RAMCleanup: 63 | @classmethod 64 | def INPUT_TYPES(s): 65 | return { 66 | "required": { 67 | "anything": (any, {}), 68 | "clean_file_cache": ("BOOLEAN", {"default": True, "label": "清理文件缓存"}), 69 | "clean_processes": ("BOOLEAN", {"default": True, "label": "清理进程内存"}), 70 | "clean_dlls": ("BOOLEAN", {"default": True, "label": "清理未使用DLL"}), 71 | "retry_times": ("INT", { 72 | "default": 3, 73 | "min": 1, 74 | "max": 10, 75 | "step": 1, 76 | "label": "重试次数" 77 | }), 78 | }, 79 | "optional": {}, 80 | "hidden": { 81 | "unique_id": "UNIQUE_ID", 82 | "extra_pnginfo": "EXTRA_PNGINFO", 83 | } 84 | } 85 | 86 | RETURN_TYPES = (any,) 87 | RETURN_NAMES = ("output",) 88 | OUTPUT_NODE = True 89 | FUNCTION = "clean_ram" 90 | CATEGORY = "Memory Management" 91 | 92 | def get_ram_usage(self): 93 | memory = psutil.virtual_memory() 94 | return memory.percent, memory.available / (1024 * 1024) 95 | 96 | def clean_ram(self, anything, clean_file_cache, clean_processes, clean_dlls, retry_times, unique_id=None, extra_pnginfo=None): 97 | try: 98 | current_usage, available_mb = self.get_ram_usage() 99 | print(f"开始清理RAM - 当前使用率: {current_usage:.1f}%, 可用: {available_mb:.1f}MB") 100 | 101 | system = platform.system() 102 | for attempt in range(retry_times): 103 | 104 | if clean_file_cache: 105 | try: 106 | if system == "Windows": 107 | ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0) 108 | elif system == "Linux": 109 | try: 110 | subprocess.run(["sudo", "sh", "-c", "echo 3 > /proc/sys/vm/drop_caches"], 111 | check=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 112 | print("使用sudo清理缓存成功") 113 | except Exception as sudo_e: 114 | print(f"使用sudo清理缓存失败: {str(sudo_e)}") 115 | try: 116 | subprocess.run(["sudo", "sysctl", "vm.drop_caches=3"], 117 | check=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 118 | print("使用sysctl清理缓存成功") 119 | except Exception as sysctl_e: 120 | print(f"使用sysctl清理缓存失败: {str(sysctl_e)}") 121 | print("请尝试在终端执行: 'sudo sh -c \"echo 3 > /proc/sys/vm/drop_caches\"'") 122 | except Exception as e: 123 | print(f"清理文件缓存失败: {str(e)}") 124 | 125 | if clean_processes: 126 | cleaned_processes = 0 127 | if system == "Windows": 128 | for process in psutil.process_iter(['pid', 'name']): 129 | try: 130 | handle = ctypes.windll.kernel32.OpenProcess( 131 | wintypes.DWORD(0x001F0FFF), 132 | wintypes.BOOL(False), 133 | wintypes.DWORD(process.info['pid']) 134 | ) 135 | ctypes.windll.psapi.EmptyWorkingSet(handle) 136 | ctypes.windll.kernel32.CloseHandle(handle) 137 | cleaned_processes += 1 138 | except: 139 | continue 140 | elif system == "Linux": 141 | cleaned_processes = 0 142 | 143 | if clean_dlls: 144 | try: 145 | if system == "Windows": 146 | ctypes.windll.kernel32.SetProcessWorkingSetSize(-1, -1, -1) 147 | elif system == "Linux": 148 | 149 | subprocess.run(["sync"], check=True) 150 | except Exception as e: 151 | print(f"释放内存资源失败: {str(e)}") 152 | 153 | time.sleep(1) 154 | current_usage, available_mb = self.get_ram_usage() 155 | print(f"清理后内存使用率: {current_usage:.1f}%, 可用: {available_mb:.1f}MB") 156 | 157 | print(f"清理完成 - 最终内存使用率: {current_usage:.1f}%, 可用: {available_mb:.1f}MB") 158 | 159 | except Exception as e: 160 | print(f"RAM清理过程出错: {str(e)}") 161 | 162 | return (anything,) 163 | 164 | 165 | WEB_DIRECTORY = "web" 166 | NODE_CLASS_MAPPINGS = { 167 | "VRAMCleanup": VRAMCleanup, 168 | "RAMCleanup": RAMCleanup, 169 | } 170 | 171 | NODE_DISPLAY_NAME_MAPPINGS = { 172 | "VRAMCleanup": "🎈VRAM-Cleanup", 173 | "RAMCleanup": "🎈RAM-Cleanup", 174 | } 175 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "comfyui_memory_cleanup" 3 | description = "A ComfyUI extension that provides nodes for memory cleanup, including VRAM and RAM cleanup functions to optimize ComfyUI performance during long running workflows." 4 | version = "1.1.1" 5 | dependencies = ["psutil"] 6 | 7 | [project.urls] 8 | Repository = "https://github.com/LAOGOU-666/Comfyui-Memory_Cleanup" 9 | # Used by Comfy Registry https://comfyregistry.org 10 | 11 | [tool.comfy] 12 | PublisherId = "laogou666" 13 | DisplayName = "Comfyui-Memory_Cleanup" 14 | Icon = "" 15 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | psutil -------------------------------------------------------------------------------- /web/vram.js: -------------------------------------------------------------------------------- 1 | import { app } from "../../scripts/app.js"; 2 | import { api } from "../../scripts/api.js"; 3 | app.registerExtension({ 4 | name: "memory.cleanup", 5 | init() { 6 | api.addEventListener("memory_cleanup", ({ detail }) => { 7 | if (detail.type === "cleanup_request") { 8 | console.log("收到内存清理请求"); 9 | fetch("/free", { 10 | method: "POST", 11 | headers: { 12 | "Content-Type": "application/json", 13 | }, 14 | body: JSON.stringify(detail.data) 15 | }) 16 | .then(response => { 17 | if (response.ok) { 18 | console.log("内存清理请求已发送"); 19 | } else { 20 | console.error("内存清理请求失败"); 21 | } 22 | }) 23 | .catch(error => { 24 | console.error("发送内存清理请求出错:", error); 25 | }); 26 | } 27 | }); 28 | } 29 | }); 30 | --------------------------------------------------------------------------------