Skip to content

Commit dcc3927

Browse files
davidhooclaude
andcommitted
perf: increase HNSW M from 8 to 16 for better ANN recall at 60K+ people scale
M=8 was causing missed candidates near the similarity threshold boundary. Also bumps efConstruction from 20 to 32 (= 2*M per HNSW guidelines) to improve graph quality during index build. Build time ~5min vs prior ~2.5min; peak CPU unchanged due to existing duty-cycle throttle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c770523 commit dcc3927

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

backend/internal/service/person_merge_suggestion_ann.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
const (
1111
annSearchK = 50 // neighbors per prototype query
12-
annHNSWM = 8 // max neighbors per node; 8 halves build time vs 16 with negligible recall loss at this scale
12+
annHNSWM = 16 // max neighbors per node; 16 gives better recall at 60K+ scale vs 8
1313
annHNSWEfSearch = 100 // search beam width; high value ensures recall near threshold boundary
1414
)
1515

@@ -94,10 +94,10 @@ func (s *personMergeSuggestionService) buildANNIndex() (*annIndex, error) {
9494
}
9595

9696
g := newHNSWGraph()
97-
// Use lower efSearch during construction for speed; the graph quality is
98-
// primarily determined by M=8. Restore to annHNSWEfSearch before returning
99-
// so search queries use full beam width.
100-
g.EfSearch = 20
97+
// Use lower efSearch during construction for speed; graph quality is
98+
// primarily determined by M. Use 2*M as efConstruction per HNSW guidelines.
99+
// Restore to annHNSWEfSearch before returning so search queries use full beam width.
100+
g.EfSearch = 32
101101
faceOwner := make(map[uint]uint, len(personProtos)*peoplePrototypeCount)
102102

103103
nodes := make([]hnsw.Node[uint], 0, len(personProtos)*peoplePrototypeCount)

0 commit comments

Comments
 (0)