From 169758d42f5e23eb2aefd26d890c75949b352d41 Mon Sep 17 00:00:00 2001 From: kshitij Date: Thu, 6 Aug 2026 05:13:51 +0530 Subject: [PATCH] =?UTF-8?q?perf(tests):=20cut=20test=5Fhermes=5Fstate.py?= =?UTF-8?q?=2052s=20->=2010s=20=E2=80=94=20kill=20sleep=20throttle=20+=20p?= =?UTF-8?q?er-row=20seeding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_hermes_state.py was the slowest file in the suite (46.7s in CI's durations cache) and therefore the LPT floor: no test slice can finish faster than its slowest file, which caps how far slicing the test matrix wider can cut the merge-gate critical path. Profiling (cProfile on the slowest tests) found the time was dead, not work: 1. time.sleep in optimize_fts_storage's inter-chunk throttle — 4.1s of a 4.6s migration test. The throttle exists so a LIVE gateway/CLI sharing the DB isn't starved of the write lock; tests run against a private tmp-path DB with no concurrent process, so the sleep protects nobody. New autouse fixture zeroes _FTS_REBUILD_MIN_PAUSE / _FTS_REBUILD_DUTY_FACTOR for this file (~20s saved). No test asserts on wall-clock pacing, so nothing weakens. 2. TestGetMessagesPagination._seed appending 3000 messages one append_message (= one commit, and off WAL one fsync) at a time — ~10s of seeding before the query under test even ran. Switched to append_messages_batch (one write transaction), the API the docstring of which exists for exactly this shape. The perf contract the seed feeds still discriminates: measured 11 progress-handler steps on the indexed path vs 855 on the forced scan path, against the unchanged 300 threshold. Measured (local, 3 runs + canonical runner): before: 187 passed in 51.8s after: 187 passed in 9.1-16.1s (canonical scripts/run_tests.sh: 14.9s) Zero production code touched; 187 tests before and after. --- tests/test_hermes_state.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/tests/test_hermes_state.py b/tests/test_hermes_state.py index 23e6f7725199f..4d8eecfa2ea5b 100644 --- a/tests/test_hermes_state.py +++ b/tests/test_hermes_state.py @@ -78,6 +78,24 @@ def db(tmp_path): session_db.close() +@pytest.fixture(autouse=True) +def _no_fts_rebuild_throttle(monkeypatch): + """Zero the FTS-rebuild inter-chunk throttle for every test in this file. + + ``optimize_fts_storage`` sleeps ``max(_FTS_REBUILD_MIN_PAUSE, + chunk_cost * _FTS_REBUILD_DUTY_FACTOR)`` between chunks so a LIVE + gateway/CLI sharing the DB isn't starved of the write lock. Tests run + against a private tmp-path DB with no concurrent process — the sleep + protects nobody and was pure dead time (measured: 4.1s of a 4.6s + migration test was time.sleep; ~20s across the file, whose total was + ~52s). The duty-cycle POLICY (sleep >= 4x chunk cost) stays covered by + the production constants themselves; no test asserts on wall-clock + pacing. + """ + monkeypatch.setattr(SessionDB, "_FTS_REBUILD_MIN_PAUSE", 0.0) + monkeypatch.setattr(SessionDB, "_FTS_REBUILD_DUTY_FACTOR", 0.0) + + # ========================================================================= # Connection lifecycle # ========================================================================= @@ -3564,8 +3582,19 @@ class TestGetMessagesPagination: def _seed(self, db, n=10): db.create_session(session_id="s1", source="cli") - for i in range(n): - db.append_message("s1", "user" if i % 2 == 0 else "assistant", f"msg-{i}") + # One write transaction for the whole seed: per-row append_message + # pays a commit (and, off WAL, an fsync) per message, which at + # n=3000 was ~10s of pure seeding before the query under test ran. + db.append_messages_batch( + "s1", + [ + { + "role": "user" if i % 2 == 0 else "assistant", + "content": f"msg-{i}", + } + for i in range(n) + ], + ) def test_default_returns_all_messages(self, db): self._seed(db)