perf(vectors): single-component bulk declare + MPS default (init ~143s → 44s)#381
Merged
Conversation
cocoindex flushes target writes once per processing component; coco.mount_each made one component per file → one Lance merge_insert (+ fsync) per file → 1168 fragments / 1170 manifest commits, ~91s of kernel I/O on a 1167-file repo (84% of init time). Iterate walk_dir().items() in ONE component instead → all declare_row calls flush as one merge_insert per table. process_*_file stay @coco.fn(memo=True) and _RowHandler.reconcile skips rows whose fingerprint is unchanged, so increment stays correct and proportional (no-change: 2.4s/0 new fragments; 1-file change: 10.2s/+1 fragment). MPS default for the embedder on Apple Silicon (free in the child process; operator overrides with SBERT_DEVICE=cpu). Measured on Shopizer (1167 files / ~3500 chunks): init end-to-end ~143s cold → 44s; vectors 119.7s → 40.4s; sys 91.2s → 4.2s; fragments 1168 → 1. The single-component loop is the supported workaround for cocoindex#2219 (native cross-component sink batching, open upstream). Refs: cocoindex#2219. Follow-ups: #379, #380. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cuts full
initfrom ~143s (cold) / ~98s (warm) → ~44s on Shopizer (1167 files / ~3500 chunks) by eliminating a per-file Lance transaction storm in the vectors phase — the phase that was ~84% of init time. The fix stays entirely inside cocoindex (no bypass, no schema/search change, increment stays correct and proportional).Root cause
cocoindex flushes target writes once per processing component, batching all
declare_rowcalls inside a component into a singlemerge_insert.coco.mount_eachcreates one component per source file, so a 1167-file repo produced 1168 Lance fragments / 1170 manifest commits — onemerge_insert(+ fsync) per file. Measured: the vectors phase spent 91.2s of kernelsystime on commit I/O alone. This is open upstream as cocoindex#2219 ("Support batching for target state sinks from different components").Non-bottlenecks confirmed by measurement (don't chase):
parse_javais Rust tree-sitter (~0.9s total), embedding is ~27s CPU / ~16s MPS, optimize is ~1.4s. The sink was purely the per-file commit granularity.Changes (
java_index_flow_lancedb.pyonly, +34/−19)app_mainnow iterateswalk_dir().items()in oneasync forloop instead of threecoco.mount_eachcalls → all chunks flush as onemerge_insertper table.process_*_filestay@coco.fn(memo=True), and_RowHandler.reconcileskips rows whose fingerprint is unchanged, so increment stays correct and proportional. Randomuuid4()ids are only generated on a memo miss (changed file); on a memo hit coco replays the recorded target state (same ids/content) → reconcile skips.SBERT_DEVICE=cpu.Measured (Shopizer)
sys)Correctness
JAVA_CODEBASE_RAG_RUN_HEAVY=1, incl. cocoindex init/increment/reprocess lifecycle tests).Notes / follow-ups
incrementre-iterates all files so coco can fingerprint them for memo/reconcile (~3s on 1167 files). When #2219 lands we can revert tomount_eachfor per-file source-memo (no re-visit) while keeping bulk-load fast — tracked in perf(vectors): adopt cocoindex native cross-component batching (#2219) when available; revert single-component loop #380.incrementwhen no Clients/Producers exist #379.🤖 Generated with Claude Code