Skip to content

perf: cache all prepared statements at load time#2

Open
mageroni wants to merge 1 commit into
htekdev:mainfrom
mageroni:perf/cache-prepared-statements
Open

perf: cache all prepared statements at load time#2
mageroni wants to merge 1 commit into
htekdev:mainfrom
mageroni:perf/cache-prepared-statements

Conversation

@mageroni

Copy link
Copy Markdown

Summary

db.prepare() was called inline on every poll cycle (every 10s) and on every tool invocation, causing repeated SQL compilation overhead that was completely avoidable.

Change

Pre-compile all statements once into a stmts object at module load time. Every db.prepare(...).run/get/all(...) call is replaced with stmts.<name>.run/get/all(...).

No behaviour changes — only the compilation cost is eliminated.

Impact

Over an 8-hour session with 10s polling:

  • ~2,880 poll cycles × 5+ prepare() calls each = ~14,400+ unnecessary compilations avoided
  • Tool invocations (send_message, reply_to_message, get_message, get_agents) each eliminate 1–4 prepare() calls

Bonus: get_agents now uses SELECT with explicit columns instead of SELECT *, avoiding fetching the unused metadata and registered_at columns.

Part of a larger perf audit

This is the highest-impact / lowest-effort item from a 10-item performance audit:

  1. Cache prepared statements ← this PR
  2. Run cleanupStaleData periodically (not just at startup)
  3. Add composite index for rate-limit query (sender, recipient, created_at)
  4. Add index on created_at for cleanup queries
  5. Add PRAGMA mmap_size for memory-mapped I/O
  6. Batch rate-limit checks across the message poll batch
  7. Deduplicate git-walk logic in onSessionStart
  8. Skip queue depth COUNT when message count is low
  9. Skip re-registration in onSessionStart when cwd is unchanged
  10. Prune agent_description from getActivePeers when not displayed

db.prepare() was called inline on every poll cycle (every 10s) and
on every tool invocation, causing repeated SQL compilation overhead.

Pre-compile all statements once into a 'stmts' object at module load
time. No behaviour changes — only the compilation cost is eliminated.

Over an 8-hour session with 10s polling that's ~2,880 poll cycles ×
5+ prepare() calls each = ~14,400+ unnecessary compilations avoided.

Also eliminates SELECT * in get_agents — now selects only the columns
actually rendered in the output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant