Skip to content

Reduce CPU semantic-search embedding overhead without degrading retrieval #407

Description

@Acters

Summary

Reduce first-build semantic-search indexing time on CPU without assuming a particular batching algorithm or silently degrading retrieval quality. The current q8 embedding pipeline batches documents by count, but real code chunks vary widely in token length, so padding and dynamic quantization make both performance and output dependent on batch composition.

Current Behavior

Embedder.embedDocuments() processes sequential fixed-count batches. The upstream default is 32 documents, using Xenova/all-MiniLM-L6-v2 with dtype: "q8" and device: "cpu".

On a measured 14,576-chunk local corpus:

  • Actual truncated input: 2.89 million tokens
  • Fixed-32 padded input: 7.34 million tokens
  • Estimated padding waste: 60.7%

A stratified 1,024-document CPU/q8 benchmark on an Intel i7-9750H produced:

Fixed batch size Time Throughput Final RSS
1 15.9s 64.3 docs/s 310 MiB
2 27.3s 37.6 docs/s 376 MiB
4 35.5s 28.9 docs/s 533 MiB
8 44.9s 22.8 docs/s 777 MiB
16 52.8s 19.4 docs/s 1,211 MiB
32 55.7s 18.4 docs/s 2,089 MiB
64 54.4s 18.8 docs/s 4,006 MiB
128 49.8s 20.6 docs/s 7,620 MiB

Concurrent single-document calls at concurrency 1, 2, 8, and 32 remained within approximately 63-66 docs/s, suggesting that extra JavaScript concurrency does not improve this CPU workload. Progress reporting can be coalesced independently from the inference batch size.

Batch composition also changes q8 vectors. Repeating the same fixed-32 schedule was deterministic, but alternate schedules produced mean cosine near 0.993 versus fixed-32, minimum cosine near 0.98, and 17-19/20 overlap for one vector-only top-20 query. This establishes schedule-dependent output, not which schedule has better retrieval quality.

Proposed Behavior

Evaluate the CPU embedding policies against the same end-to-end workloads, then implement the smallest policy that improves indexing time and memory without degrading final search retrieval. Candidate policies include single-document inference with coalesced progress, length-aware fixed-count batches, and padded-token-budget batches; none is prescribed before integration and retrieval testing.

Acceptance Criteria

  • Add a reproducible benchmark that includes tokenizer work, ONNX inference, production progress callbacks, and Embedder/IndexManager integration.
  • Compare the current fixed-32 baseline with at least single-document inference and one length-aware policy on representative mixed-length corpora.
  • Record runtime, progress cadence, and memory methodology; do not infer transient peak RSS from post-batch samples alone.
  • Preserve the positional chunk-to-vector contract through IndexManager.embedChunks() for any policy that reorders work.
  • Add integration coverage proving vectors are stored under the correct chunk IDs.
  • Build a small, reviewable retrieval benchmark from mechanically grounded identifier, path, and natural-language queries; exclude disputed labels after independent review.
  • Compare final search results using retrieval metrics such as Recall@5 and first-relevant rank, not vector cosine alone.
  • Coalesce progress updates independently from inference calls if the selected policy uses small batches.
  • Rebuild or version existing embeddings if the selected policy changes q8 document vectors.
  • Keep GPU acceleration, model replacement, dtype changes, ranking redesign, and incremental persistence out of scope.

Technical Notes

Relevant files:

  • packages/semantic-search/src/embedder.ts
  • packages/semantic-search/src/index-manager.ts
  • packages/semantic-search/src/search.ts
  • packages/semantic-search/test/index-manager.test.ts
  • packages/semantic-search/test/search-engine.test.ts

Exact token-length preprocessing took 13.4 seconds for the measured 14,576-document corpus and must be included when evaluating token-aware policies. Prototype scheduling tests covered empty input, oversized singletons, budget and count limits, stable ties, exactly-once scheduling, and output-order restoration, but production integration remains untested.

The original semantic-search design discussion is available at #108.

Suggested Labels

bug, P1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions