Further performance optimization
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// searchSectionCap bounds how many rows each results section renders. The
|
||||
@@ -46,7 +47,7 @@ type searchPageData struct {
|
||||
PageTotal int
|
||||
FileTotal int
|
||||
IndexBuiltAt time.Time
|
||||
RenderMS int64
|
||||
renderTimer
|
||||
}
|
||||
|
||||
// indexEntry is the shared scoreable core of both folder and file index
|
||||
@@ -132,7 +133,7 @@ func (h *handler) handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||
IndexBuiltAt: builtAt,
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
data.RenderMS = elapsedMS(r)
|
||||
data.renderTimer = renderTimer{requestStart(r)}
|
||||
if err := searchTmpl.ExecuteTemplate(w, "layout", data); err != nil {
|
||||
log.Printf("search template error: %v", err)
|
||||
}
|
||||
@@ -278,7 +279,7 @@ func scoreName(nameLower string, nameTokens []string, qLower string, qTokens []s
|
||||
if best < 20 {
|
||||
best = 20
|
||||
}
|
||||
case fuzzy && levenshtein(w, qt) <= 2:
|
||||
case fuzzy && withinTwoEdits(w, qt):
|
||||
if best < 5 {
|
||||
best = 5
|
||||
}
|
||||
@@ -575,6 +576,17 @@ func tokenize(s string) []string {
|
||||
return tokens
|
||||
}
|
||||
|
||||
// withinTwoEdits reports whether a and b are at most 2 edits apart. Lengths
|
||||
// differing by more than 2 rule that out without running levenshtein, which
|
||||
// skips nearly every word pair in the per-query scoring loop.
|
||||
func withinTwoEdits(a, b string) bool {
|
||||
d := utf8.RuneCountInString(a) - utf8.RuneCountInString(b)
|
||||
if d < -2 || d > 2 {
|
||||
return false
|
||||
}
|
||||
return levenshtein(a, b) <= 2
|
||||
}
|
||||
|
||||
// levenshtein returns the edit distance between a and b. Operates on runes so
|
||||
// multi-byte characters count as one edit.
|
||||
func levenshtein(a, b string) int {
|
||||
|
||||
Reference in New Issue
Block a user