Skip to content

Limit IVF append metadata work to affected clusters - #145

Merged
gouyt13 merged 1 commit into
mainfrom
perf/ivf-sparse-append
Oct 21, 2026
Merged

gouyt13 merged 1 commit into
mainfrom
perf/ivf-sparse-append

Conversation

@gouyt13

@gouyt13 gouyt13 commented Oct 21, 2026

Copy link
Copy Markdown
Member

Summary

Appending even one vector currently allocates metadata for every IVF cluster and recreates every cluster view. This makes small appends pay a cost proportional to the total cluster count.

Group incoming rows by the clusters they touch, keep each cluster's staging storage and tail buffer with its append state, and refresh only the affected views. Cap quantization workers to the number of touched clusters while preserving row order, reserved-capacity reuse, and the strong exception guarantee.

Add a sparse, interleaved-cluster regression covering L2/IP and 1/4/32-bit storage, including reserved-pointer stability and byte-for-byte comparison with a full rebuild. Public APIs, saved-index formats, and dependencies are unchanged.

Testing

  • GCC 14.3 Release with native optimization disabled: cmake --build <build> --target rabitq_tests --parallel 4, then ctest --test-dir <build> -R '^Ivf' --output-on-failure -j 2: 35 passed.
  • ./scripts/check-format.sh, git diff --check, and ./scripts/check-tidy.sh <build-tidy>: passed; clang-tidy 23 covered all configured first-party translation units.
  • Additional local harnesses (not committed): 262 allocation-failure injections and 6 mid-operation rotation failures preserved state and allowed successful retries. 16 append/rebuild comparisons, touching 37 clusters across L2/IP, 1/4/9/32-bit storage and 1/4 threads, produced identical complete saved indexes.
  • Validation ran on Linux x86-64 with AVX-512. The final revision was not rerun under Python, sanitizers, or ARM. The existing vendored hnswlib unused-function warning is present in both baseline and candidate builds.

Matched append benchmarks against main@841ca5e: deterministic synthetic float32 data, dimension 65, L2, fixed data/rotation seeds, Xeon Gold 6418H, GCC 14.3 -O3 -DNDEBUG, native optimization OFF, runtime AVX-512, one thread pinned to CPU 16. Only IVF::add is timed; construction, loading, saving, and search are excluded.

Each variant ran in four interleaved processes (ABBA repeated twice), with one warmup and 31 measured appends per process for the small case, or 15 for the batch case. Values below are the median and range of the four process medians.

Workload main PR
4096 clusters, 4096 base points, append 1 point to one supplied cluster, 1-bit 26.776 us [26.469, 26.937] 3.711 us [3.610, 3.847]
256 clusters, 8192 base points, append 2048 automatically routed points, 4-bit 12.399 ms [11.534, 13.095] 11.945 ms [11.862, 12.100]

Complete saved-index SHA-256 and search-result hashes match between main and the PR in both workloads. Batch timing ranges overlap on this shared host; they do not establish a general batch speedup.

Group incoming IVF rows by touched cluster and keep each cluster's
staging state together. Update only changed views and bound workers
to the touched cluster count. Cover sparse interleaved appends and
reserved storage with a rebuild-equivalence regression.
@gouyt13
gouyt13 merged commit c23c1b7 into main Oct 21, 2026
45 checks passed
@gouyt13
gouyt13 deleted the perf/ivf-sparse-append branch October 21, 2026 06:24
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