From aeafa28342e7a94150117bb44b747cf5d5f8f5a4 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:24:18 +0530 Subject: [PATCH] perf(config): read_raw_config serves cache hits without _CONFIG_LOCK `_read_raw_config_impl` had the same lock-on-hit shape #117440 removed from `_load_config_impl`: a microsecond cache hit queued behind `_CONFIG_LOCK`, which `save_config()` holds across an atomic YAML write, so one background config write stalled every raw read (per-turn policy checks on the gateway). `_RAW_CONFIG_CACHE` already publishes each entry as one `(*sig, data)` tuple replaced wholesale, so the lock never protected the read; check the signature first without it and fall through to the locked re-parse on a miss. --- hermes_cli/config.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hermes_cli/config.py b/hermes_cli/config.py index 2267d98616..babd04f421 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -1962,6 +1962,20 @@ def cfg_get(cfg: Optional[Dict[str, Any]], *keys: str, default: Any = None) -> A def _read_raw_config_impl(*, want_deepcopy: bool) -> Dict[str, Any]: + # Lock-free fast path for cache hits — same shape as `_load_config_impl`. `_RAW_CONFIG_CACHE` + # publishes each entry as ONE `(*sig, data)` tuple replaced wholesale, so a reader sees either + # the complete old entry or the complete new one; `_CONFIG_LOCK` only serializes the re-parse + # and the writers (`save_config()` holds it across an atomic YAML write, which used to stall + # every cached read for the duration). A lost race just falls through to the locked re-check. + try: + config_path = get_config_path() + cache_key = file_signature(config_path.stat()) + cached = _RAW_CONFIG_CACHE.get(str(config_path)) + if cached is not None and cached[:len(cache_key)] == cache_key: + return copy.deepcopy(cached[len(cache_key)]) if want_deepcopy else cached[len(cache_key)] + except Exception: + pass + with _CONFIG_LOCK: try: config_path = get_config_path()