Repository navigation
SIFT1M benchmark and faster distance functions - #2
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP
vector_distance decoded both arguments into new []float32 slices for every row scanned. It now decodes values inside an unrolled distance loop with no allocations. vector_distance_q computes the distance from int8 differences and scales once, since dequantization is affine; dequantize is removed. On SIFT1M (1M x 128, k=100, single thread) p50 query latency drops from 733 ms to 362 ms for float32 and from 659 ms to 339 ms for int8, with unchanged recall. README adds a PRAGMA mmap_size tip (246 ms float32). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP
The implementation plan is complete. CLAUDE.md drops the rules that depended on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP
* bump zombiezen.com/go/sqlite for function error fix v1.4.2 shadowed err in resultError, so errors returned from SQL functions were silently dropped. The fix (zombiezen/go-sqlite#133) is merged but not yet tagged, so this pins the main pseudo-version. Un-skips the error tests that were blocked on it and removes the obsolete stub-error test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP * add vector_index virtual table vector_index stores vectors in chunks of 1024 inside shadow tables and answers k-nearest neighbor queries by reading whole chunks and scanning them in Go across GOMAXPROCS goroutines, instead of evaluating a SQL function per row. Supports float32 and int8 storage, k = ? and LIMIT (with OFFSET), rowid lookups, full scans, INSERT/UPDATE/DELETE, rename, and drop. Reconnecting with a different dimension or quantization range is an error. SIFT1M p50 (k=100, default settings): 139 ms float32 and 46 ms int8, versus 363 ms and 336 ms for the scalar functions. Inserting 1M vectors takes 9.8 s (float32) and 6.5 s (int8). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP * size vector_index chunks by bytes and add chunk_size Chunks held a fixed 1024 vectors, which is 512 KiB at 128 dimensions but 6 MiB at 1536. A sweep over 128, 768, and 1536 dimensions and chunk data sizes from 64 KiB to 4 MiB found search fastest near 1 MiB and inserts 4.5-16x slower at 4 MiB than at 1 MiB, for both float32 and int8. The default capacity is now max(1, 1 MiB / vector bytes). A chunk_size=N argument overrides it. Both are stored in name_info at creation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP --------- Co-authored-by: Claude Opus 5 <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
sift_test.go, behind thesiftbuild tag) that reports insert time, single-threaded query latency, and recall@1/10/100 against the published ground truth.bench/sift_compare.py(uv inline script) that runs the same queries through sqlite-vec, FAISS, and hnswlib for comparison. Results are in the README.vector_distancenow computes distance directly on the blob bytes in an unrolled loop, with no per-row allocations. Previously it decoded both arguments into new[]float32slices for every row.vector_distance_qcomputes the distance from int8 differences and scales once, since dequantization is affine.dequantizeis removed.PRAGMA mmap_sizetip.Results
SIFT1M: 1M vectors × 128 dimensions, k=100, one thread, Apple M3 Max, default SQLite settings.
vector_distance(float32)vector_distance_q(int8)Recall is unchanged. With
PRAGMA mmap_size = 1 GiB, float32 queries take 246 ms. For comparison, sqlite-vec'svec_distance_l2takes 306 ms andvec0takes 143 ms under default settings.Behavior notes
Testing
go vet ./...andgo vet -tags sift ./...go test -race ./...go test -tags sift -run TestSIFT1M -timeout 0 -v -sift.dir .tmp/sift🤖 Generated with Claude Code
https://claude.ai/code/session_01PTvMD95uUfGT1jasgFsLdP