package store import ( "context" "fmt" "math" "math/rand" "path/filepath" "testing" ) // benchDim is the resident embedder's width (multilingual-e5-small, 384), so // the per-row decode cost the benchmark measures is the real one. const benchDim = 384 // seedMemVectors fills a fresh store with n L2-normalized rows carrying a meta // blob the size recall actually stores — the note text plus its type — because // the cost this benchmark exists to measure is unmarshalling that blob for // every row when only topK survivors need it. func seedMemVectors(tb testing.TB, n int) *MemoryStore { tb.Helper() path := filepath.Join(tb.TempDir(), "mem_bench.db") st, err := Open(context.Background(), path) if err != nil { tb.Fatalf("Open: %v", err) } tb.Cleanup(func() { _ = st.Close() }) m := st.VectorMemory() rng := rand.New(rand.NewSource(1)) ctx := context.Background() for i := 0; i < n; i++ { if err := m.Insert(ctx, fmt.Sprintf("note:%d", i), randUnitVec(rng, benchDim), map[string]string{ "type": "note", "text": fmt.Sprintf("заметка номер %d о том, что надо не забыть сделать на неделе", i), }); err != nil { tb.Fatalf("Insert %d: %v", i, err) } } return m } func randUnitVec(rng *rand.Rand, dim int) []float32 { v := make([]float32, dim) var norm float64 for i := range v { f := rng.NormFloat64() v[i] = float32(f) norm += f * f } norm = math.Sqrt(norm) for i := range v { v[i] = float32(float64(v[i]) / norm) } return v } // BenchmarkMemoryStoreSearch measures one recall query against a store of n // rows. Row counts bracket the documented scale: 1000 is a plausible today, // 10000 is the "thousands, not millions" ceiling the type doc claims a full // scan is fine at. func BenchmarkMemoryStoreSearch(b *testing.B) { for _, n := range []int{1000, 10000} { b.Run(fmt.Sprintf("rows=%d", n), func(b *testing.B) { m := seedMemVectors(b, n) q := randUnitVec(rand.New(rand.NewSource(2)), benchDim) ctx := context.Background() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := m.Search(ctx, q, 10); err != nil { b.Fatal(err) } } }) } }