1717from config import SERVICES , INSTALL_DIR , DATA_DIR , LLM_BACKEND
1818from models import ServiceStatus , DiskUsage , ModelInfo , BootstrapStatus
1919
20+
21+ class _DirSizeCache :
22+ """Per-path TTL cache for dir_size_gb to avoid repeated rglob walks."""
23+
24+ def __init__ (self , ttl : float = 60.0 ):
25+ self ._ttl = ttl
26+ self ._store : dict [str , tuple [float , float ]] = {}
27+
28+ def get (self , path : Path ) -> float | None :
29+ key = str (path .resolve ())
30+ entry = self ._store .get (key )
31+ if entry is None :
32+ return None
33+ expires_at , value = entry
34+ if time .monotonic () > expires_at :
35+ del self ._store [key ]
36+ return None
37+ return value
38+
39+ def set (self , path : Path , value : float ):
40+ self ._store [str (path .resolve ())] = (time .monotonic () + self ._ttl , value )
41+
42+
43+ _dir_size_cache = _DirSizeCache ()
44+
2045# Lemonade serves at /api/v1 instead of llama.cpp's /v1
2146_LLM_API_PREFIX = "/api/v1" if LLM_BACKEND == "lemonade" else "/v1"
2247
@@ -307,8 +332,13 @@ def dir_size_gb(path: Path) -> float:
307332 """Calculate total size of a directory in GB. Returns 0.0 if path doesn't exist.
308333
309334 Skips symlinks to avoid following links outside DATA_DIR and double-counting.
335+ Results are cached for 60 seconds to avoid repeated expensive rglob walks.
310336 """
337+ cached = _dir_size_cache .get (path )
338+ if cached is not None :
339+ return cached
311340 if not path .exists ():
341+ _dir_size_cache .set (path , 0.0 )
312342 return 0.0
313343 total = 0
314344 try :
@@ -320,7 +350,19 @@ def dir_size_gb(path: Path) -> float:
320350 pass
321351 except (PermissionError , OSError ):
322352 pass
323- return round (total / (1024 ** 3 ), 2 )
353+ result = round (total / (1024 ** 3 ), 2 )
354+ _dir_size_cache .set (path , result )
355+ return result
356+
357+
358+ def invalidate_dir_size_cache (path : Path ):
359+ """Remove cached size for a specific path after it has been modified."""
360+ _dir_size_cache ._store .pop (str (path .resolve ()), None )
361+
362+
363+ def clear_dir_size_cache ():
364+ """Clear the entire dir_size_gb cache (e.g. after bulk operations)."""
365+ _dir_size_cache ._store .clear ()
324366
325367
326368def get_disk_usage () -> DiskUsage :
0 commit comments