Files
proffesor-for-testing__agen…/docs/benchmark-hnsw-vector-loading.md
Profa 367a5ce409 feat: KG integration into test generation + 276x faster vector loading
Two features in this commit:

1. Knowledge Graph context now flows into test generation pipeline.
   When `aqe code index .` populates vectors, test generation produces
   +78% more assertions and +2.9% higher coverage estimates by using
   KG dependency and semantic similarity data.

2. Replaced pure JS HNSW index with RuvectorFlatIndex backed by
   @ruvector/gnn (Rust/NAPI). Vector loading drops from 16-18s to 65ms
   (276x faster), recall improves from 70% to 100%, memory drops 3.4x,
   and per-query search stays comparable (3.4ms vs 2.3ms).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:52:51 +00:00

74 lines
3.4 KiB
Markdown

# HNSW Vector Loading Performance Benchmark
## Problem
Loading 5,073 HNSW vectors (768 dimensions) at CLI startup took ~16-18 seconds due to the pure JavaScript HNSW graph construction algorithm. The `InMemoryHNSWIndex` rebuilt the full navigable small-world graph on every session start, with O(n * efConstruction * log(n) * dim) complexity.
## Solution
Replaced `InMemoryHNSWIndex` (pure JS HNSW) with `RuvectorFlatIndex` — a flat vector store that uses `@ruvector/gnn` (Rust/NAPI) for native differentiable search ranking, with pre-cached L2 norms for fast cosine similarity scoring.
Key optimizations:
- **No graph construction at load time** — vectors stored flat as `Float32Array`, O(1) per insert
- **Native Rust ranking** via `@ruvector/gnn differentiableSearch` for top-k candidate selection
- **Pre-cached norms** at insert time — cosine similarity reduces to dot product + 1 division
- **Zero-copy Float32Array** — no `Array.from()` conversions between search and scoring
- **Float32Array buffer view** for SQLite BLOB deserialization (replaces per-element `readFloatLE`)
## Benchmark Configuration
| Parameter | Value |
|-----------|-------|
| Vectors | 5,073 |
| Dimensions | 768 (MiniLM all-MiniLM-L6-v2) |
| Search queries | 100 |
| k (top results) | 5 |
| Platform | Linux aarch64, Node.js v24.13.0 |
| Native backend | @ruvector/gnn v0.1.22 (Rust/NAPI) |
## Results
| Implementation | Build (ms) | Search (ms) | Avg/query (ms) | Memory (MB) | Recall |
|---|---:|---:|---:|---:|---:|
| Pure JS HNSW (efC=200) + readFloatLE **[OLD]** | 17,951 | 234 | 2.34 | 85 | 70.2% |
| Pure JS HNSW (efC=200) + Float32Array deser | 16,062 | 390 | 3.90 | 98 | 69.8% |
| Pure JS HNSW (efC=50) + Float32Array deser | 10,612 | 258 | 2.58 | 72 | 69.2% |
| Pure JS HNSW (efC=50) + readFloatLE | 9,161 | 223 | 2.23 | 96 | 65.8% |
| @ruvector/gnn raw (Rust, no cosine scores) | 4 | 877 | 8.77 | 2 | 100.0% |
| **RuvectorFlatIndex [NEW]** | **65** | **337** | **3.37** | **25** | **100.0%** |
## Summary
| Metric | Old | New | Change |
|---|---|---|---|
| Build/load time | 17,951ms | 65ms | **276x faster** |
| Search per query | 2.34ms | 3.37ms | ~same (1.4x) |
| Recall accuracy | 70.2% | 100.0% | **Perfect** |
| Memory usage | 85MB | 25MB | **3.4x less** |
### Why search is ~same speed despite brute-force
At 5,073 vectors, the HNSW graph traversal advantage (O(log n)) is offset by:
- HNSW's JS-level cosine similarity calls during beam search
- Cache-friendly sequential Float32Array scan in flat index
- Pre-cached norms eliminating redundant norm computation
HNSW graph construction only pays off above ~50k vectors where the O(log n) search savings exceed the O(n * efConstruction) build cost.
### Why recall improved from 70% to 100%
HNSW is an **approximate** nearest neighbor algorithm. With M=16 and efSearch=100, it misses ~30% of true nearest neighbors due to the greedy graph traversal. The flat index computes exact distances against all candidates.
## Files Changed
- `v3/src/kernel/unified-memory-hnsw.ts` — Added `RuvectorFlatIndex` class with pre-cached norms
- `v3/src/kernel/unified-memory.ts` — Swapped `InMemoryHNSWIndex` to `RuvectorFlatIndex`, optimized `bufferToFloatArray`
- `v3/scripts/benchmark-hnsw-loading.ts` — Benchmark script (6 implementations compared)
## Reproducing
```bash
npm run build
npx tsx v3/scripts/benchmark-hnsw-loading.ts
```