persona-ui / utils /preload.py
Jac-Zac
Adding probing and suppport for the latest version of the code
d8ae160
from __future__ import annotations
import importlib
import logging
import threading
import time
from collections.abc import Iterable
from typing import Any
logger = logging.getLogger(__name__)
_started: set[tuple[str, ...]] = set()
_lock = threading.Lock()
def _warm_imports(
modules: tuple[str, ...],
functions: tuple[str, ...],
calls: tuple[tuple[str, tuple[Any, ...]], ...],
delay_seconds: float,
) -> None:
if delay_seconds > 0:
time.sleep(delay_seconds)
for module in modules:
try:
importlib.import_module(module)
except Exception:
logger.debug("Background preload failed for %s", module, exc_info=True)
for function_path in functions:
try:
module_name, function_name = function_path.split(":", 1)
function = getattr(importlib.import_module(module_name), function_name)
function()
except Exception:
logger.debug(
"Background preload failed for %s", function_path, exc_info=True
)
for function_path, args in calls:
try:
module_name, function_name = function_path.split(":", 1)
function = getattr(importlib.import_module(module_name), function_name)
function(*args)
except Exception:
logger.debug(
"Background preload failed for %s%r",
function_path,
args,
exc_info=True,
)
def preload_once(
name: str,
*,
modules: Iterable[str] = (),
functions: Iterable[str] = (),
calls: Iterable[tuple[str, tuple[Any, ...]]] = (),
delay_seconds: float = 0.25,
) -> None:
"""Warm small predictable costs on a daemon thread after the visible render.
Keep this limited to imports and tiny metadata. Avoid model construction
and full tensor loads because those can steal enough CPU or I/O to make the
visible page feel slower.
"""
module_tuple = tuple(dict.fromkeys(modules))
function_tuple = tuple(dict.fromkeys(functions))
call_tuple = tuple((path, tuple(args)) for path, args in calls)
if not module_tuple and not function_tuple and not call_tuple:
return
key = (name, *module_tuple, *function_tuple, repr(call_tuple))
with _lock:
if key in _started:
return
_started.add(key)
thread = threading.Thread(
target=_warm_imports,
args=(module_tuple, function_tuple, call_tuple, delay_seconds),
name=f"persona-ui-preload-{name}",
daemon=True,
)
thread.start()