Files
ai-agent/scripts/bench_lists.py
Gabriel Vidal 48b5ab441c docs+tools: bench-lists.sh and perf rules 5-7
Reproducible snapshot benchmark of the list hot paths (throwaway
--network none container, optionally against a worktree's backend), and the
three new rules in CLAUDE.md's performance section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-29 19:22:55 +02:00

71 lines
2.0 KiB
Python

"""Conversation-list hot-path timings — run via scripts/bench-lists.sh.
Imports the backend (no startup hooks run, so no threads) against a copy of /data."""
import threading
import time
import main
store, meta = main.store, main.meta_store
def raw(fn):
"""The handler's own dict, past `_json_in_worker`'s JSONResponse (if any)."""
return getattr(fn, "__wrapped__", fn)
conversations_list = raw(main.conversations_list)
conversation_summary = raw(main.conversation_summary)
def bump():
"""What one transcript write does to the caches."""
store.summaries_version += 1
def t(label, fn, n=3):
best = 1e9
for _ in range(n):
bump()
t0 = time.perf_counter()
fn()
best = min(best, time.perf_counter() - t0)
print(f"{label:<44} {best*1000:8.0f} ms")
return best
store.all_summaries() # warm the decode cache (a one-off at boot)
print("summaries:", len(store.all_summaries()), " meta entries:", len(meta.all()))
first = conversations_list(limit=50)["conversations"][0]["id"]
t("_skills_by_path", main._skills_by_path)
t("_build_agent_runs", main._build_agent_runs)
t("_summaries_with_account", main._summaries_with_account)
t("_conversation_cards(full=False)", lambda: main._conversation_cards(False))
t("GET /api/conversations?limit=50", lambda: conversations_list(limit=50))
t("GET /api/conversation-summary (1 id)", lambda: conversation_summary(first))
def herd(k):
"""k clients refetching the list right after one transcript write."""
bump()
ths = [threading.Thread(target=conversations_list, kwargs={"limit": 50})
for _ in range(k)]
t0 = time.perf_counter()
for th in ths:
th.start()
for th in ths:
th.join()
print(f"{'herd x' + str(k) + ' (wall, after one write)':<44} "
f"{(time.perf_counter() - t0)*1000:8.0f} ms")
herd(1)
herd(4)
herd(8)
# Steady state: nothing changed, repeat request.
t0 = time.perf_counter()
conversations_list(limit=50)
print(f"{'list, unchanged versions (warm)':<44} {(time.perf_counter()-t0)*1000:8.0f} ms")