Skip to content

refactor(sqlite): optimize vector-search, shard-manager, transcript-manager#12

Merged
ZeR020 merged 3 commits into
mainfrom
refactor/sqlite-vector-optimization
May 7, 2026
Merged

refactor(sqlite): optimize vector-search, shard-manager, transcript-manager#12
ZeR020 merged 3 commits into
mainfrom
refactor/sqlite-vector-optimization

Conversation

@ZeR020

@ZeR020 ZeR020 commented May 7, 2026

Copy link
Copy Markdown
Owner

Changes

  • Prepared statement caching in VectorSearch: Added WeakMap-based statement cache per database handle. Eliminates re-preparation overhead for insertVector, deleteVector, updateVector, listMemories, getAllMemories, getMemoryById, countVectors.
  • Shard manager statement caching: Moved all ShardManager prepared statements to constructor-initialized cached properties (activeShardStmt, allShardsStmt, scopedShardsStmt, createShardStmt).
  • Diversity filter optimization: Pre-computes word sets with a Map cache in searchAcrossShards, avoiding repeated string splitting in the O(n²) comparison loop.
  • Token count optimization: Replaced regex-based split() in approximateTokenCount with a char-code scan loop — faster and avoids regex compilation overhead.
  • Cleaned up getAllShards: Removed duplicated SQL preparation logic, unified to cached statements with ternary dispatch.

Impact

  • -77 lines, +85 lines — net +8 lines for significant performance gains
  • SQLite statement reuse — reduces parse/plan overhead on hot paths
  • Diversity check — O(n²) loop now uses cached word sets instead of repeated split()
  • Token counting — O(n) char scan instead of O(n) regex split

Testing

  • TypeScript compilation: clean
  • All 173 tests pass

Requesting @coderabbitai full review for additional optimization opportunities in the SQLite/vector layer and across the codebase.

Summary by CodeRabbit

  • Refactor
    • Improved database performance with cached prepared statements to reduce query overhead and speed up operations.
    • Updated token estimation to a character-based heuristic for more consistent token counts.
    • Enhanced search diversity filtering by caching word-sets and using set-based similarity, improving result variety and selection efficiency.

Copilot AI review requested due to automatic review settings May 7, 2026 11:35
@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 26b644de-813b-4dc6-bec1-24dda71a92f5

📥 Commits

Reviewing files that changed from the base of the PR and between 13cfae4 and 28e6955.

📒 Files selected for processing (1)
  • src/services/sqlite/vector-search.ts

📝 Walkthrough

Walkthrough

Caches prepared SQLite statements in VectorSearch and ShardManager; searchAcrossShards caches per-memory word-sets and computes Jaccard similarity; TranscriptManager replaces approximateTokenCount with a character-based heuristic.

Changes

SQLite Performance Optimization

Layer / File(s) Summary
VectorSearch Statement Cache Infrastructure
src/services/sqlite/vector-search.ts
Adds stmtCache (WeakMap) and getStmt helper to cache prepared statements per database handle.
VectorSearch INSERT via Cache
src/services/sqlite/vector-search.ts
insertVector uses a cached prepared INSERT statement rather than preparing inline each call.
VectorSearch Diversity Filtering Optimization
src/services/sqlite/vector-search.ts
searchAcrossShards caches per-memory word-sets and computes Jaccard similarity from cached sets instead of rebuilding sets per comparison.
VectorSearch CRUD Operations via Cache
src/services/sqlite/vector-search.ts
deleteVector, updateVector, listMemories, getAllMemories, getMemoryById, and countVectors use cached prepared statements.
ShardManager Statement Caching
src/services/sqlite/shard-manager.ts
Constructor precompiles activeShardStmt, allShardsStmt, scopedShardsStmt, and createShardStmt; getActiveShard, getAllShards, and createShard use cached statements.
TranscriptManager Token Counting
src/services/sqlite/transcript-manager.ts
approximateTokenCount refactored to a character-iteration heuristic with whitespace-transition counting and scaling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 In nests of SQL I quietly stash,

Prepared statements saved in a flash,
Word-sets kept for diverse recall,
Tokens counted by each character's fall,
I hop through rows and speed them all.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides detailed changes, impact metrics, and testing confirmation, but deviates significantly from the repository's required template structure and missing required checklist items. Reformat description using the repository template: add Type of Change section, complete the Checklist with specific build/test results, and explicitly document testing methodology and any related issues.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main refactoring focus: optimization of three SQLite-related modules through statement caching and algorithmic improvements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/sqlite-vector-optimization

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/services/sqlite/vector-search.ts (1)

459-464: ⚡ Quick win

Avoid per-comparison allocations in Jaccard calculation.

Line 462 and Line 463 still allocate intermediate arrays/sets inside the O(n²) loop. You can compute intersection/union directly from set sizes.

♻️ Proposed allocation-free Jaccard inner loop
-        const intersectionSize = [...candidateWords].filter((w) => selectedWords.has(w)).length;
-        const unionSize = new Set([...candidateWords, ...selectedWords]).size;
+        let intersectionSize = 0;
+        const [smaller, larger] =
+          candidateWords.size <= selectedWords.size
+            ? [candidateWords, selectedWords]
+            : [selectedWords, candidateWords];
+        for (const w of smaller) {
+          if (larger.has(w)) intersectionSize++;
+        }
+        const unionSize = candidateWords.size + selectedWords.size - intersectionSize;
         const jaccard = unionSize > 0 ? intersectionSize / unionSize : 0;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/sqlite/vector-search.ts` around lines 459 - 464, The Jaccard
calculation inside the loop (using candidateWords, selectedWords, getWordSet,
finalResults, and jaccard) currently allocates temporary arrays/sets via
[...candidateWords].filter(...) and new Set([...candidateWords,
...selectedWords]) on every comparison; replace this with an allocation-free
approach: iterate the smaller Set (candidateWords or selectedWords) and count
intersectionSize by checking set.has(item), then compute unionSize as
candidateWords.size + selectedWords.size - intersectionSize and compute jaccard
= unionSize > 0 ? intersectionSize / unionSize : 0; update the inner loop to use
this method to avoid per-comparison allocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/sqlite/transcript-manager.ts`:
- Around line 27-33: The current loop counts every whitespace character which
overestimates tokens; instead detect token boundaries by incrementing count only
when you transition from a whitespace to a non-whitespace character. In the
function using variables text, count and ch (the block that currently loops over
text and returns Math.ceil((count + 1) * 1.33)), track previousCharIsSpace (or
prevIsSpace) and only increment count when prevIsSpace is true and current ch is
non-whitespace; initialize prevIsSpace = true to count the first token correctly
and keep the final Math.ceil scaling unchanged.

---

Nitpick comments:
In `@src/services/sqlite/vector-search.ts`:
- Around line 459-464: The Jaccard calculation inside the loop (using
candidateWords, selectedWords, getWordSet, finalResults, and jaccard) currently
allocates temporary arrays/sets via [...candidateWords].filter(...) and new
Set([...candidateWords, ...selectedWords]) on every comparison; replace this
with an allocation-free approach: iterate the smaller Set (candidateWords or
selectedWords) and count intersectionSize by checking set.has(item), then
compute unionSize as candidateWords.size + selectedWords.size - intersectionSize
and compute jaccard = unionSize > 0 ? intersectionSize / unionSize : 0; update
the inner loop to use this method to avoid per-comparison allocations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d7a1f59-6fd1-49b7-a9ad-ca733152fcbe

📥 Commits

Reviewing files that changed from the base of the PR and between 6e35f4e and 53c870a.

📒 Files selected for processing (3)
  • src/services/sqlite/shard-manager.ts
  • src/services/sqlite/transcript-manager.ts
  • src/services/sqlite/vector-search.ts

Comment thread src/services/sqlite/transcript-manager.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/sqlite/vector-search.ts`:
- Around line 441-453: getWordSet currently tokenises on whitespace so words
with punctuation (e.g. "important.") remain distinct; update getWordSet to
extract alphabetic word runs instead (use a word-boundary/letter regex like
match(/[a-z]+/g) after toLowerCase) and fall back to an empty array when match
returns null before building the Set; keep using wordSetCache and the same cache
key but ensure you cache the normalized set built from the regex tokens to fix
the Jaccard undercounting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a9ad570-09e5-4133-9eb4-e711f3f593d8

📥 Commits

Reviewing files that changed from the base of the PR and between 53c870a and 13cfae4.

📒 Files selected for processing (2)
  • src/services/sqlite/transcript-manager.ts
  • src/services/sqlite/vector-search.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/services/sqlite/transcript-manager.ts

Comment thread src/services/sqlite/vector-search.ts
@ZeR020
ZeR020 merged commit d1e8478 into main May 7, 2026
5 checks passed
@ZeR020
ZeR020 deleted the refactor/sqlite-vector-optimization branch May 7, 2026 12:48
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.

2 participants