mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
feat(config): improve symlink cache logging and add performance timing
- Add `time` import for performance measurement - Change debug logs to info level for better visibility of cache operations - Add detailed logging for cache validation failures and successes - Include timing metrics for symlink initialization and scanning - Log cache save/load operations with mapping counts
This commit is contained in:
30
py/config.py
30
py/config.py
@@ -6,6 +6,7 @@ from typing import Any, Dict, Iterable, List, Mapping, Optional, Set
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import time
|
||||||
|
|
||||||
from .utils.settings_paths import ensure_settings_file, get_settings_dir, load_settings_template
|
from .utils.settings_paths import ensure_settings_file, get_settings_dir, load_settings_template
|
||||||
|
|
||||||
@@ -282,21 +283,24 @@ class Config:
|
|||||||
def _load_symlink_cache(self) -> bool:
|
def _load_symlink_cache(self) -> bool:
|
||||||
cache_path = self._get_symlink_cache_path()
|
cache_path = self._get_symlink_cache_path()
|
||||||
if not cache_path.exists():
|
if not cache_path.exists():
|
||||||
|
logger.info("Symlink cache not found at %s", cache_path)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with cache_path.open("r", encoding="utf-8") as handle:
|
with cache_path.open("r", encoding="utf-8") as handle:
|
||||||
payload = json.load(handle)
|
payload = json.load(handle)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.debug("Failed to load symlink cache %s: %s", cache_path, exc)
|
logger.info("Failed to load symlink cache %s: %s", cache_path, exc)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not isinstance(payload, dict):
|
if not isinstance(payload, dict):
|
||||||
|
logger.info("Symlink cache payload is not a dict: %s", type(payload))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cached_fingerprint = payload.get("fingerprint")
|
cached_fingerprint = payload.get("fingerprint")
|
||||||
cached_mappings = payload.get("path_mappings")
|
cached_mappings = payload.get("path_mappings")
|
||||||
if not isinstance(cached_fingerprint, dict) or not isinstance(cached_mappings, Mapping):
|
if not isinstance(cached_fingerprint, dict) or not isinstance(cached_mappings, Mapping):
|
||||||
|
logger.info("Symlink cache missing fingerprint or path mappings")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
current_fingerprint = self._build_symlink_fingerprint()
|
current_fingerprint = self._build_symlink_fingerprint()
|
||||||
@@ -307,12 +311,14 @@ class Config:
|
|||||||
or not isinstance(cached_stats, Mapping)
|
or not isinstance(cached_stats, Mapping)
|
||||||
or sorted(cached_roots) != sorted(current_fingerprint["roots"]) # type: ignore[index]
|
or sorted(cached_roots) != sorted(current_fingerprint["roots"]) # type: ignore[index]
|
||||||
):
|
):
|
||||||
|
logger.info("Symlink cache invalidated: roots changed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for root in current_fingerprint["roots"]: # type: ignore[assignment]
|
for root in current_fingerprint["roots"]: # type: ignore[assignment]
|
||||||
cached_stat = cached_stats.get(root) if isinstance(cached_stats, Mapping) else None
|
cached_stat = cached_stats.get(root) if isinstance(cached_stats, Mapping) else None
|
||||||
current_stat = current_fingerprint["stats"].get(root) # type: ignore[index]
|
current_stat = current_fingerprint["stats"].get(root) # type: ignore[index]
|
||||||
if not isinstance(cached_stat, Mapping) or not current_stat:
|
if not isinstance(cached_stat, Mapping) or not current_stat:
|
||||||
|
logger.info("Symlink cache invalidated: missing stats for %s", root)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cached_mtime = cached_stat.get("mtime_ns")
|
cached_mtime = cached_stat.get("mtime_ns")
|
||||||
@@ -321,6 +327,7 @@ class Config:
|
|||||||
current_inode = current_stat.get("inode")
|
current_inode = current_stat.get("inode")
|
||||||
|
|
||||||
if cached_inode != current_inode:
|
if cached_inode != current_inode:
|
||||||
|
logger.info("Symlink cache invalidated: inode changed for %s", root)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if cached_mtime != current_mtime:
|
if cached_mtime != current_mtime:
|
||||||
@@ -332,6 +339,7 @@ class Config:
|
|||||||
and cached_mtime == cached_noise
|
and cached_mtime == cached_noise
|
||||||
and current_mtime == current_noise
|
and current_mtime == current_noise
|
||||||
):
|
):
|
||||||
|
logger.info("Symlink cache invalidated: mtime changed for %s", root)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
normalized_mappings: Dict[str, str] = {}
|
normalized_mappings: Dict[str, str] = {}
|
||||||
@@ -341,6 +349,7 @@ class Config:
|
|||||||
normalized_mappings[self._normalize_path(target)] = self._normalize_path(link)
|
normalized_mappings[self._normalize_path(target)] = self._normalize_path(link)
|
||||||
|
|
||||||
self._path_mappings = normalized_mappings
|
self._path_mappings = normalized_mappings
|
||||||
|
logger.info("Symlink cache loaded with %d mappings", len(self._path_mappings))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _save_symlink_cache(self) -> None:
|
def _save_symlink_cache(self) -> None:
|
||||||
@@ -353,22 +362,37 @@ class Config:
|
|||||||
try:
|
try:
|
||||||
with cache_path.open("w", encoding="utf-8") as handle:
|
with cache_path.open("w", encoding="utf-8") as handle:
|
||||||
json.dump(payload, handle, ensure_ascii=False, indent=2)
|
json.dump(payload, handle, ensure_ascii=False, indent=2)
|
||||||
|
logger.info("Symlink cache saved to %s with %d mappings", cache_path, len(self._path_mappings))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.debug("Failed to write symlink cache %s: %s", cache_path, exc)
|
logger.info("Failed to write symlink cache %s: %s", cache_path, exc)
|
||||||
|
|
||||||
def _initialize_symlink_mappings(self) -> None:
|
def _initialize_symlink_mappings(self) -> None:
|
||||||
|
start = time.perf_counter()
|
||||||
if not self._load_symlink_cache():
|
if not self._load_symlink_cache():
|
||||||
self._scan_symbolic_links()
|
self._scan_symbolic_links()
|
||||||
self._save_symlink_cache()
|
self._save_symlink_cache()
|
||||||
|
logger.info(
|
||||||
|
"Symlink mappings rebuilt and cached in %.2f ms",
|
||||||
|
(time.perf_counter() - start) * 1000,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.info("Loaded symlink mappings from cache")
|
logger.info(
|
||||||
|
"Symlink mappings restored from cache in %.2f ms",
|
||||||
|
(time.perf_counter() - start) * 1000,
|
||||||
|
)
|
||||||
self._rebuild_preview_roots()
|
self._rebuild_preview_roots()
|
||||||
|
|
||||||
def _scan_symbolic_links(self):
|
def _scan_symbolic_links(self):
|
||||||
"""Scan all symbolic links in LoRA, Checkpoint, and Embedding root directories"""
|
"""Scan all symbolic links in LoRA, Checkpoint, and Embedding root directories"""
|
||||||
|
start = time.perf_counter()
|
||||||
visited_dirs: Set[str] = set()
|
visited_dirs: Set[str] = set()
|
||||||
for root in self._symlink_roots():
|
for root in self._symlink_roots():
|
||||||
self._scan_directory_links(root, visited_dirs)
|
self._scan_directory_links(root, visited_dirs)
|
||||||
|
logger.info(
|
||||||
|
"Symlink scan finished in %.2f ms with %d mappings",
|
||||||
|
(time.perf_counter() - start) * 1000,
|
||||||
|
len(self._path_mappings),
|
||||||
|
)
|
||||||
|
|
||||||
def _scan_directory_links(self, root: str, visited_dirs: Set[str]):
|
def _scan_directory_links(self, root: str, visited_dirs: Set[str]):
|
||||||
"""Iteratively scan directory symlinks to avoid deep recursion."""
|
"""Iteratively scan directory symlinks to avoid deep recursion."""
|
||||||
|
|||||||
Reference in New Issue
Block a user