diff --git a/.gitignore b/.gitignore index c4ac184b..c442b436 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ Thumbs.db # ===================== .vscode/ .idea/ +.venv/ diff --git a/.jules/bolt.md b/.jules/bolt.md index 398b9b36..355db886 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -45,3 +45,7 @@ ## 2026-02-10 - Group-By for Multi-Count Statistics **Learning:** Executing multiple `count()` queries with different filters (e.g., for different statuses) causes redundant database scans and network round-trips. **Action:** Use a single SQL `GROUP BY` query to fetch counts for all categories/statuses at once, then process the results in Python. + +## 2026-02-11 - File I/O in Hot Paths +**Learning:** Checking file modification time (`os.path.getmtime`) in a property getter seems harmless ("just a stat call"), but when accessed multiple times per request (e.g., fetching 4 different config values sequentially), the redundant disk I/O compounds and introduces measurable synchronous latency. +**Action:** Throttle filesystem checks in hot-reloading configurations. Even a small interval (e.g., 5 seconds) effectively eliminates redundant I/O during a single request's lifecycle without sacrificing the ability to hot-reload. diff --git a/backend/adaptive_weights.py b/backend/adaptive_weights.py index 944618ba..5b35d4cf 100644 --- a/backend/adaptive_weights.py +++ b/backend/adaptive_weights.py @@ -12,6 +12,7 @@ class AdaptiveWeights: _instance = None _weights = None _last_loaded = 0 + _last_checked = 0 def __new__(cls): if cls._instance is None: @@ -40,8 +41,12 @@ def _load_weights(self): self._weights = {} def _check_reload(self): - # Optimization: Checking mtime is fast (stat call). - self._load_weights() + # Throttle mtime checks to at most once every 5 seconds + # This prevents multiple disk I/O operations per request + current_time = time.time() + if current_time - self._last_checked > 5: + self._last_checked = current_time + self._load_weights() def _save_weights(self): try: