Skip to content

Repository files navigation

vector-db

CI

A high-performance, in-memory vector database written in C++20, with SIMD-accelerated distance computation, three search backends, write-ahead-log persistence, and a REST API.

Features

  • Three search backends, selectable per database:
    • Exact (KD-tree) — exact nearest-neighbor search
    • LSH — locality-sensitive hashing for fast approximate search
    • HNSW — hierarchical navigable small-world graphs (hnswlib-style) for high-recall approximate search
  • SIMD distance kernels — AVX2/FMA on x86-64, NEON on ARM (Apple Silicon), with scalar fallbacks; toggleable at runtime
  • Durability — write-ahead log with automatic checkpointing, atomic file writes, and a recovery state machine that replays the log on startup
  • Deletes and updates on approximate indexes — LSH/HNSW graphs cannot delete in place, so the database tracks stale index entries, over-fetches and re-ranks search candidates against the live vector set, and rebuilds indexes once stale entries outnumber live ones
  • LRU query cache keyed on (query, k), invalidated on every mutation
  • Atomic batch operations — insert / update / delete many vectors per call
  • REST API server (cpp-httplib) exposing the full CRUD + search + admin surface
  • Thread-safe — a concurrency test hammers parallel inserts and searches

Layout

src/core/           Vector type, KD-tree, VectorDatabase orchestration
src/algorithms/     HNSW and LSH approximate indexes
src/optimizations/  SIMD kernels (AVX2 / NEON), parallel processing helpers
src/features/       WAL persistence, atomic batch insert, query cache, recovery
src/api/            REST server (vector_db_server)
src/utils/          Distance metrics (Euclidean, cosine), RNG
tests/              GoogleTest suite (17 tests)
bench/              Reproducible benchmark harness with JSON output

Build

Requires CMake ≥ 3.20 and a C++20 compiler. Dependencies (nlohmann/json, cpp-httplib, GoogleTest) are fetched automatically.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

Test

ctest --test-dir build --output-on-failure

The suite covers hand-computed distance values, SIMD-vs-scalar agreement, KD-tree correctness against brute force, HNSW/LSH recall floors, CRUD round-trips, delete/update visibility in search, cache behavior, batch atomicity, checkpoint/recovery, and concurrent access.

There is also a standalone smoke test that runs all three backends end to end:

./build/basic_usage

REST server

./build/vector_db_server --dims 128 --port 8080
# Insert
curl -X POST localhost:8080/vectors \
  -d '{"key": "doc1", "vector": [0.1, 0.2, ...], "metadata": "optional"}'

# Search
curl -X POST localhost:8080/search -d '{"query": [0.1, 0.2, ...], "k": 10}'

# CRUD
curl localhost:8080/vectors/doc1
curl -X DELETE localhost:8080/vectors/doc1

# Health / stats
curl localhost:8080/health
curl localhost:8080/stats

Batch endpoints (/vectors/batch/*), recovery controls (/recovery/*), and runtime configuration (algorithm, distance metric, SIMD toggle) are also exposed.

Benchmarks

A reproducible harness measures insert throughput, query latency (p50/p95/p99), recall-vs-latency Pareto curves for HNSW (ef_search sweep) and LSH (table/hash sweep), and SIMD-vs-scalar speedup:

./build/bench/vdb_bench            # full run, writes bench/results/results.json
./build/bench/vdb_bench --quick    # smaller sizes for CI

Results include machine/compiler metadata and a fixed RNG seed so runs are comparable. See bench/results/results.json for the latest numbers from an Apple M-series machine.

Using as a library

vector-db can be consumed from another CMake project via add_subdirectory, which exposes the vector_db::vdb_core target and the single public header <vdb/vector_index.hpp>:

add_subdirectory(path/to/vector-db)
target_link_libraries(app PRIVATE vector_db::vdb_core)
#include <vdb/vector_index.hpp>

int main() {
    vdb::IndexOptions options;
    options.backend = vdb::IndexOptions::Backend::HNSW;
    options.metric = vdb::IndexOptions::Metric::Cosine;

    vdb::VectorIndex index(4, options);
    index.insert("a", {1.0f, 0.0f, 0.0f, 0.0f});
    index.insert("b", {0.0f, 1.0f, 0.0f, 0.0f});

    auto results = index.search({1.0f, 0.0f, 0.0f, 0.0f}, /*k=*/1);
    return results.empty() ? 1 : 0;
}

nlohmann_json is fetched automatically as a dependency of the core persistence layer. googletest and httplib are fetched only when VDB_BUILD_TESTS / VDB_BUILD_SERVER are enabled, which is the default for top-level builds but not when the project is pulled in via add_subdirectory.

See examples/consumer for a minimal end-to-end consumer project exercised by CI.

Design notes

  • Source of truth is an in-memory hash map of key → vector. Indexes are acceleration structures; search results are always validated against the map, which is what makes deletes/updates correct on top of append-only ANN indexes.
  • Persistence follows a WAL + checkpoint model: every mutation is logged before acknowledgment, checkpoints snapshot the full map atomically (write-temp-then-rename), and recovery replays the log over the last checkpoint.
  • Locking is a single database-level mutex; the KD-tree uses tombstones for O(1) logical deletion.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages