Skip to content

perf: salvage query/serialization cluster — session-search I/O, adaptive hydration, Anthropic client reuse, parallel model fetches - #86764

Merged
teknium1 merged 9 commits into
mainfrom
salvage/w2-query-perf
Aug 15, 2026
Merged

teknium1 merged 9 commits into
mainfrom
salvage/w2-query-perf

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Salvages the wave-2 query/serialization hot-path cluster: four contributor perf PRs covering session-search I/O, discovery hydration, Anthropic client reuse, and parallel model-list fetches.

Changes

Excluded

Validation

Check Result
tests/tools/test_session_search.py ✅ 53 passed
tests/test_hermes_state.py ✅ pass (one failure pre-exists on origin/main, verified in a clean worktree)
tests/run_agent/test_token_persistence_non_cli.py ✅ pass
tests/agent/test_anthropic_request_client_reuse.py ✅ pass
tests/hermes_cli/test_model_cache_parallel_prefetch.py ✅ pass
Combined run 256 passed, 1 pre-existing-on-main failure

Prompt-cache/invariant review: none of these touch conversation context, message alternation, or the system prompt. The Anthropic client cache key covers every input that must force a rebuild (credential rotation, base URL/region, timeout, 1M-beta flag).

Credits

Covers #77034, #82595, #77144, #80415. Fixes #80413.

Infographic

Query & serialization perf infographic

Adolanium and others added 9 commits August 14, 2026 23:09
Every search route in _search_messages_impl (FTS, CJK bigram, trigram,
LIKE fallback, rebuild-gap supplement) selected m.content, then the
result tail popped it unread. On DBs with multi-MB tool rows, each
search read and materialized up to `limit` full rows only to discard
them. Snippets come from snippet()/substr() in SQL and the context
window is re-fetched by id, so no code path ever read the column.

Drop the column from all six SELECT lists. Returned dicts are
unchanged: content was never part of the public result (the pop ran
before return), and tests/test_hermes_state.py already documents that
contract.

(cherry picked from commit d0c3af1)
…rebuilding it per call

_create_request_anthropic_client() built a fresh anthropic.Anthropic
client (and httpx pool) on every single LLM call, and
_close_request_anthropic_client() always fully closed it right after
- unlike the OpenAI-wire path, which caches and reuses one warm
client across sequential calls via a single-slot cache keyed on the
effective client kwargs.

Add the same single-slot cache to the Anthropic-wire path: keyed on
credentials, base URL/Bedrock region, per-model timeout, and the
1M-beta flag; in_use guards concurrent calls from sharing one pool's
close/abort lifecycle; poisoned marks a cross-thread-aborted slot so
the owner-thread close discards it; reuse only on request_complete /
stream_request_complete (the same _REQUEST_CLIENT_REUSE_REASONS the
OpenAI path already uses). Wires a teardown hook into
release_clients()/close() mirroring _close_cached_request_openai_client.

Fixes #HPA-02

(cherry picked from commit 37f90df)
When the 1h provider_models_cache.json TTL lapses, the model picker
serially fetches /v1/models for each authenticated provider. With 10+
providers this stacks to 15-30s of blocking before the picker renders.

Add a parallel prefetch step before the serial picker build loops:
- _collect_authed_provider_slugs(): lightweight credential pre-scan
  that mirrors sections 1/2/2b without fetching model lists
- _prefetch_provider_models_parallel(): ThreadPoolExecutor-based
  concurrent fetch of stale/missing cache entries (max 8 workers)
- update_provider_cache_entry(): thread-safe single-entry cache writer
  with threading.Lock to prevent concurrent write races

Guardrails:
- Skipped when <=3 authed providers (overhead not worth it)
- Skipped when refresh=True (serial path force-refreshes)
- Exception-isolated (falls back to serial path on any failure)
- No behavioral change (same model lists, same picker output)

Closes #80413

(cherry picked from commit 89dddd6)
… wrapper

Main extracted a session_search() wrapper (owned-DB lifecycle) around
_session_search_impl after #82595 was opened; the cherry-picked detail
parameter landed on the impl only. Append it to the wrapper with the
same positional-compatibility contract and pass it through.
@alt-glitch alt-glitch added type/perf Performance improvement or optimization P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/tools Tool registry, model_tools, toolsets labels Aug 15, 2026
@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 9f2b8af — chore(contributors): map lepetitprince716@gmail.com -> lepet

⚠️ Warnings

CI timings · View report · View job

Wall time 18m45s vs 9m47s (+91.7%). 11 job(s) slower, 12 faster, 2 unchanged.

  • Python tests / Run tests slice 4/12: +66.0s
  • Python tests / Run tests slice 8/12: -39.0s
  • Python tests / Run tests slice 2/12: +33.0s
  • Python tests / Run tests slice 12/12: +32.0s
  • Python tests / Run tests slice 3/12: +30.0s

OSV vulnerability scan · View job

5 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/perf Performance improvement or optimization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: parallelize provider model-list fetches in model picker (serial /v1/models bottleneck)

6 participants