Skip to content

Commit 48b739c

Browse files
authored
Speed up levenshteinWithMax by reusing buffers (#1823)
1 parent 80cbbd9 commit 48b739c

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

internal/core/core.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"slices"
88
"sort"
99
"strings"
10+
"sync"
1011
"unicode"
1112
"unicode/utf8"
1213

@@ -476,6 +477,8 @@ func GetSpellingSuggestion[T any](name string, candidates []T, getName func(T) s
476477
maximumLengthDifference := max(2, int(float64(len(name))*0.34))
477478
bestDistance := math.Floor(float64(len(name))*0.4) + 1 // If the best result is worse than this, don't bother.
478479
runeName := []rune(name)
480+
buffers := levenshteinBuffersPool.Get().(*levenshteinBuffers)
481+
defer levenshteinBuffersPool.Put(buffers)
479482
var bestCandidate T
480483
for _, candidate := range candidates {
481484
candidateName := getName(candidate)
@@ -490,7 +493,7 @@ func GetSpellingSuggestion[T any](name string, candidates []T, getName func(T) s
490493
if len(candidateName) < 3 && !strings.EqualFold(candidateName, name) {
491494
continue
492495
}
493-
distance := levenshteinWithMax(runeName, []rune(candidateName), bestDistance-0.1)
496+
distance := levenshteinWithMax(buffers, runeName, []rune(candidateName), bestDistance-0.1)
494497
if distance < 0 {
495498
continue
496499
}
@@ -502,9 +505,25 @@ func GetSpellingSuggestion[T any](name string, candidates []T, getName func(T) s
502505
return bestCandidate
503506
}
504507

505-
func levenshteinWithMax(s1 []rune, s2 []rune, maxValue float64) float64 {
506-
previous := make([]float64, len(s2)+1)
507-
current := make([]float64, len(s2)+1)
508+
type levenshteinBuffers struct {
509+
previous []float64
510+
current []float64
511+
}
512+
513+
var levenshteinBuffersPool = sync.Pool{
514+
New: func() any {
515+
return &levenshteinBuffers{}
516+
},
517+
}
518+
519+
func levenshteinWithMax(buffers *levenshteinBuffers, s1 []rune, s2 []rune, maxValue float64) float64 {
520+
bufferSize := len(s2) + 1
521+
buffers.previous = slices.Grow(buffers.previous[:0], bufferSize)[:bufferSize]
522+
buffers.current = slices.Grow(buffers.current[:0], bufferSize)[:bufferSize]
523+
524+
previous := buffers.previous
525+
current := buffers.current
526+
508527
big := maxValue + 0.01
509528
for i := range previous {
510529
previous[i] = float64(i)

0 commit comments

Comments
 (0)