Performance problems
Covers slow queries, high memory, high disk usage, and slow cold indexing.
Symptom: queries take more than a second
Likely causes (ranked)
- Cold index still in progress — embeddings aren't populated, so ranking runs on the slower keyword + structural path.
search max_resultsis very high — you asked for 200 hits; the ranker scores 200×, assembly is proportional.context budget_tokensis maxed — 32768 tokens of assembly with a large structural-expansion budget is genuinely more work.- Very large repo +
brute_forcevector store — brute force isO(N)per query. At ~75k chunks, queries cross ~30ms; past ~200k, they start to bite.
Diagnostic
# Is embedding done?
shaktiman enrichment-status --root .
# Is the vector store the bottleneck?
time shaktiman search "your query" --root . --max 10 # keyword + structural
# vs.
time shaktiman search "your query" --root . --max 10 --mode full
Fix
- Wait for embeddings if cold-indexing is active.
- Lower
max_resultsto 10–20 for interactive use. - Swap
brute_force→hnswif the repo is big. HNSW isO(log N)and persisted to disk. - Use
locatemode (the default) unless you specifically need inline source.
Symptom: shaktimand memory grows steadily
Likely causes
- The embedding worker queue is deep (many unembedded chunks; each queued job holds the chunk text in memory briefly).
- You're running
brute_force— all vectors live in RAM by design.
Diagnostic
ps -o rss,vsz,cmd -p $(cat /path/to/project/.shaktiman/daemon.pid)
shaktiman enrichment-status --root .
Fix
- Let the queue drain (or pause edits until it does).
- For large repos, move to HNSW (disk-backed) or pgvector / qdrant (externalised).
Symptom: disk usage is surprisingly high
Breakdown (typical for 1M-line codebase)
index.db(SQLite metadata + FTS5): ~150 MBembeddings.bin(768-dim f32 vectors, ~75k chunks): ~230 MBindex.db-wal(SQLite write-ahead log, transient): up to ~20 MBshaktimand.log+ rotated copies: variable
Fix
- Set
[embedding].enabled = falseif you don't need semantic search — drops the 230 MB. - Rotate older log files (the daemon does this on startup; proxies append and don't rotate).
- If
index.dbis much larger than expected: runningVACUUMviasqlite3 index.db "VACUUM;"(with the daemon stopped) reclaims freelist space. Rare and usually unnecessary.
Symptom: cold index is painfully slow
Likely causes
- Lots of files that shouldn't be indexed (
node_modules/,vendor/, build output) aren't in.gitignore. - Very large generated files being parsed (e.g. bundled
.js, generated protobuf). - Ollama is slow, and
--embedwas set so indexing waits on embedding.
Diagnostic
# See what got indexed
shaktiman status --root . # per-language file count — surprising?
# Time a sub-tree on its own
time shaktiman index /path/to/small-subtree
Fix
- Add noise directories to
.gitignoreor.shaktimanignore. - Index without
--embedfirst (keyword-only runs much faster). Add--embedlater once the metadata index is ready. - If Ollama is the bottleneck, separate the runs:
shaktiman index .thenshaktiman index . --embedin the background.
See also
- Configuration → Backends — backend trade-offs.
- Configuration → Embeddings — batch size, timeout.
- Performance — Overview — the dedicated section (when it lands).