Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# CI for the cgo C++ SIMD core and pure-Go fallback.
#
# The matrix runs natively on amd64 (portable scalar C++ path) and arm64
# (NEON kernels), each with cgo on and off. Because the hosted runners
# already cover both Linux architectures natively, the Makefile's
# docker-verify target is intentionally NOT run here.
name: CI

on:
push:
branches: [main, banchmark]
pull_request:

jobs:
test:
name: test (${{ matrix.os }}, cgo=${{ matrix.cgo }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm] # amd64 + arm64 (NEON)
cgo: [1, 0]
env:
CGO_ENABLED: ${{ matrix.cgo }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: go vet
run: go vet ./...

- name: go build
run: go build ./...

- name: go test
run: go test ./...

gofmt:
name: gofmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: gofmt
run: |
files=$(gofmt -l .)
if [ -n "$files" ]; then
echo "The following files are not gofmt-formatted:"
echo "$files"
exit 1
fi
8 changes: 3 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ make clean
**API (`internal/api/`)**
- Gin HTTP server (`cmd/vectordb-server`)

**Legacy (`db/`, `storage/`)**
- Older brute-force engine (linear scan + top-k heap), kept as scaffold;
its Search uses the batched `CosineSimilarityMany` kernel

### Conventions for the SIMD core
- Never change `pkg/vectormath` public signatures; callers must not care
which kernel is active
Expand All @@ -101,7 +97,9 @@ make clean
locally and via `make docker-verify`

### Known quirks
- `config.yaml` contains absolute macOS paths; tests use `t.TempDir()`
- `config.yaml` uses relative paths (`data/`, `logs/`) resolved against the
process working directory — run binaries from the repo root (or pass an
absolute `-config` path and adjust the paths); tests use `t.TempDir()`

### Configuration System
- Main config file: `config.yaml` (server host/port, storage path, index
Expand Down
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ vectorDB/
│ ├── scalar/ # pure-Go kernels (CGO_ENABLED=0 + parity reference)
│ └── simd/ # C++17 SIMD core via cgo (NEON on aarch64)
├── persistence/ # BadgerDB store
├── db/, storage/ # Legacy brute-force engine + storage interfaces
├── proto/ # Protocol buffer definitions
├── docs/ # SIMD benchmark report
├── test/ # Integration tests
Expand Down Expand Up @@ -142,9 +141,9 @@ A Go→C call costs roughly 40–50 ns. That fact shaped the API:
per-pair call has to be cheap by itself. Fusion is the mitigation there.
- *Paths we control do batch*: `CosineSimilarityBatch`/`CosineSimilarityMany`
score one query against N vectors in a **single** crossing (flattened
row-major buffer, query norm computed once). The brute-force scan in
`db/engine.go` uses this — 10,000 vectors cost one crossing instead of
10,000, which is the 561 µs → 114 µs row in the tables.
row-major buffer, query norm computed once) — 10,000 vectors cost one
crossing instead of 10,000, which is the 561 µs → 114 µs row in the
tables.
- *Zero allocations*: the fused kernel reports zero-norm inputs via a NaN
sentinel instead of an out-pointer, because any Go pointer passed to C
escapes to the heap — the sentinel keeps the hot path allocation-free.
Expand All @@ -158,7 +157,7 @@ reassociates float32 additions.

### Key design points

- **Frozen public API** — every caller (`internal/index`, `db`, tests) is
- **Frozen public API** — every caller (`internal/index`, tests) is
untouched; the kernel swap is invisible above `pkg/vectormath`.
- **Pure-Go fallback** — `CGO_ENABLED=0` builds and passes the full test
suite anywhere Go runs, no C++ toolchain required.
Expand Down Expand Up @@ -287,8 +286,23 @@ index:

database:
max_vectors: 1000000

logging:
level: info
encoding: json
output_paths:
- stdout
- logs/vectordb.log
dev_mode: false

badger:
path: data
```

Paths (`storage.path`, `badger.path`, file entries in
`logging.output_paths`) are relative to the process working directory;
missing directories are created on startup.

## Development
```bash
make build
Expand Down
31 changes: 0 additions & 31 deletions cmd/main.go

This file was deleted.

6 changes: 3 additions & 3 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ server:
port: 8080

storage:
path: /Users/ishaanbajpai/Desktop/bitCamp/vectorDB/data
path: data

index:
type: hnsw
Expand All @@ -18,7 +18,7 @@ logging:
output_paths:
- stdout
- logs/vectordb.log
dev_mode: false
dev_mode: false

badger:
path: /Users/ishaanbajpai/Desktop/bitCamp/vectorDB/data
path: data
62 changes: 0 additions & 62 deletions db/badger_test.go

This file was deleted.

123 changes: 0 additions & 123 deletions db/engine.go

This file was deleted.

3 changes: 2 additions & 1 deletion docs/simd-benchmark-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ Notes:
| pure Go fused, batched | 1093 µs | 109 ns |

The batched kernel amortizes the cgo crossing to nothing and lets the NEON
loop stream; it is used by the brute-force scan in `db/engine.go`.
loop stream; it is exposed as the public
`CosineSimilarityBatch`/`CosineSimilarityMany` API.

## End-to-end HNSW (dim=128, M=16, efConstruction=200; count=3, benchtime=1000x)

Expand Down
9 changes: 9 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,14 @@ func DefaultConfig() *Config {
Database: DatabaseConfig{
MaxVectors: 1000000,
},
Logging: logger.Config{
Level: "info",
Encoding: "json",
OutputPaths: []string{"stdout"},
DevMode: false,
},
Badger: BadgerConfig{
Path: "data",
},
}
}
Loading
Loading