Skip to main content
Version: 0.4.0

SochDB Performance Issue Analysis

Problem Statement

SochDB insert performance is significantly slower than ChromaDB:

  • SochDB: 862 vec/s
  • ChromaDB: 14,258 vec/s (16.5x faster)

Root Cause Analysis

Profiling Results

Our comprehensive profiling reveals the bottleneck:

╔════════════════════════════════════════════════════════════════════════════╗
║ Time Breakdown (1000 vectors) ║
╠════════════════════════════════════════════════════════════════════════════╣
║ Phase 3: Neighbor Selection │ 10,352ms │ 80.2% │ ← MAIN BOTTLENECK ║
║ Phase 3: Add Connections │ 1,887ms │ 14.6% │ ║
║ Phase 3: Search Layer │ 476ms │ 3.7% │ ║
║ Phase 1: Quantization │ 1ms │ <0.1% │ ║
║ Phase 2: Map Insert │ 0ms │ <0.1% │ ║
║ FFI/Python Overhead │ 0ms │ <0.1% │ ║
╚════════════════════════════════════════════════════════════════════════════╝

80% of time is spent in the RNG (Relative Neighborhood Graph) neighbor selection heuristic.

Why This Happens

The HNSW algorithm uses the RNG heuristic to maintain graph quality:

  1. For each inserted vector: Search returns ~ef_construction candidates
  2. For each candidate: Check if it's "shadowed" by previously selected neighbors
  3. Each shadow check: Requires full 768-dimensional cosine distance calculation

Mathematical complexity: O(N × ef_construction × max_connections × dimension)

With our current settings:

  • N = 1000 vectors
  • ef_construction = 200
  • max_connections = 16
  • dimension = 768
  • Total distance calculations: ~3.2 million
  • Each cosine distance: 3 SIMD operations (dot product + 2 norms)

Performance vs Quality Trade-off

ef_constructionThroughputSelf-RecallSpeedup vs ef=200
50175 vec/sPoor2.3x faster
100121 vec/sMedium1.6x faster
15094 vec/sGood1.2x faster
20078 vec/sExcellentbaseline

ChromaDB vs SochDB Configuration Differences

SochDB Current Settings

VectorIndex(
dimension=768,
ef_construction=200, # High quality, slow inserts
max_connections=16, # Standard HNSW parameter
)

Likely ChromaDB Settings

ChromaDB likely uses more aggressive defaults optimized for speed:

# Estimated ChromaDB equivalent
ef_construction=50-100 # Much lower for faster inserts
max_connections=16 # Similar
# Plus potential optimizations:
# - Quantized vectors (F16/BF16)
# - Batched distance calculations
# - Simplified neighbor selection

Solutions

1. Immediate Fix: Reduce ef_construction

Change:

# Current (slow)
VectorIndex(ef_construction=200)

# Optimized (2.3x faster)
VectorIndex(ef_construction=50)

# Balanced (1.6x faster, good quality)
VectorIndex(ef_construction=100)

Expected result: 2-3x faster inserts with acceptable recall loss.

2. Medium-term Optimizations

  1. Batch Distance Computation:

    • Current: Scalar distance calculations in RNG loop
    • Optimize: Batch 8 candidates at once with SIMD (4-8x speedup)
  2. Distance Caching:

    • Cache pairwise distances between candidates
    • Avoid recomputing same distances multiple times
  3. Progressive RNG:

    • Use simple top-k selection for early inserts (sparse graph)
    • Switch to full RNG when graph becomes dense

3. Long-term Optimizations

  1. Quantization: Use F16 vectors to halve memory bandwidth
  2. Parallel RNG: Parallelize neighbor selection checks
  3. Adaptive Parameters: Auto-tune ef_construction based on graph density

Benchmark Configuration Issue

The benchmark results suggest the SochDB test was likely run with:

  • ef_construction=200 (high quality settings)
  • Single-threaded insertion
  • Full RNG heuristic

While ChromaDB likely used:

  • Lower ef_construction (~50-100)
  • Optimized insertion pipeline
  • Possibly simplified neighbor selection

Action Items

Immediate (1 hour)

  1. Change default ef_construction from 200 to 100
  2. Update benchmark to use consistent quality settings
  3. Re-run performance comparison

Short-term (1 week)

  1. Implement batched distance computation in RNG loop
  2. Add distance caching
  3. Add adaptive ef_construction based on graph size

Medium-term (1 month)

  1. Implement F16 quantization for 2x memory bandwidth improvement
  2. Parallelize neighbor selection
  3. Add comprehensive benchmarking suite

Expected Results

With ef_construction=100:

  • Insert speed: ~200-300 vec/s (3-4x improvement)
  • Recall: 95%+ (minimal quality loss)
  • Search speed: Unchanged (0.26ms)

With additional optimizations:

  • Insert speed: ~1000+ vec/s (competitive with ChromaDB)
  • Recall: 98%+ (equal or better quality)
  • Memory usage: 50% reduction with F16

Conclusion

The performance gap is algorithmic, not architectural. SochDB is using high-quality HNSW settings that prioritize recall over insert speed. ChromaDB likely uses more aggressive defaults optimized for insertion performance.

The fix is straightforward: adjust the quality vs speed trade-off to match competitive benchmarks, then optimize the hot path (neighbor selection) for production use.