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>
71 lines
2.0 KiB
Python
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")
|