Skip to content

Commit

Permalink
Merge pull request #14 from koki-develop/search-performance
Browse files Browse the repository at this point in the history
  • Loading branch information
koki-develop committed Mar 26, 2023
2 parents 5cf385d + 414baee commit c500068
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 15 deletions.
1 change: 0 additions & 1 deletion go.mod
Expand Up @@ -6,7 +6,6 @@ require (
github.com/charmbracelet/bubbles v0.15.0
github.com/charmbracelet/bubbletea v0.23.2
github.com/charmbracelet/lipgloss v0.7.1
github.com/sahilm/fuzzy v0.1.0
github.com/spf13/cobra v1.6.1
)

Expand Down
2 changes: 0 additions & 2 deletions go.sum
Expand Up @@ -18,7 +18,6 @@ github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkX
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
Expand Down Expand Up @@ -49,7 +48,6 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
Expand Down
23 changes: 11 additions & 12 deletions model.go
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/sahilm/fuzzy"
)

var (
Expand Down Expand Up @@ -35,7 +34,7 @@ type model struct {
cursorLineStyle lipgloss.Style
cursorLineMatchesStyle lipgloss.Style

matches fuzzy.Matches
matches matches
choices []int

// window
Expand All @@ -57,9 +56,9 @@ func newModel(fzf *FZF, items *items, opt *findOption) *model {
fzf.option.keymap.Toggle.SetEnabled(false)
}

var matches fuzzy.Matches
var matches matches
for i := 0; i < items.Len(); i++ {
matches = append(matches, fuzzy.Match{
matches = append(matches, match{
Str: items.String(i),
Index: i,
})
Expand Down Expand Up @@ -125,7 +124,7 @@ func (m *model) headerView() string {
// count
if m.fzf.option.countViewEnabled {
_, _ = v.WriteRune('\n')
_, _ = v.WriteString(m.fzf.option.countViewFunc(m.items.Len(), m.matches.Len(), m.windowWidth))
_, _ = v.WriteString(m.fzf.option.countViewFunc(m.items.Len(), len(m.matches), m.windowWidth))
}

return v.String()
Expand Down Expand Up @@ -250,15 +249,15 @@ func (m *model) choice() {
return
}

if m.matches.Len() == 0 {
if len(m.matches) == 0 {
return
}

m.choices = append(m.choices, m.matches[m.cursorPosition].Index)
}

func (m *model) toggle() {
if m.matches.Len() == 0 {
if len(m.matches) == 0 {
return
}

Expand Down Expand Up @@ -287,9 +286,9 @@ func (m *model) cursorDown() {
func (m *model) filter() {
s := m.input.Value()
if s == "" {
var matches fuzzy.Matches
var matches matches
for i := 0; i < m.items.Len(); i++ {
matches = append(matches, fuzzy.Match{
matches = append(matches, match{
Str: m.items.String(i),
Index: i,
})
Expand All @@ -298,7 +297,7 @@ func (m *model) filter() {
return
}

m.matches = fuzzy.FindFrom(s, m.items)
m.matches = fuzzySearch(m.items, s)
}

func (m *model) fixCursor() {
Expand All @@ -308,7 +307,7 @@ func (m *model) fixCursor() {
}

if m.cursorPosition+1 > len(m.matches) {
m.cursorPosition = len(m.matches) - 1
m.cursorPosition = max(len(m.matches)-1, 0)
return
}
}
Expand All @@ -327,7 +326,7 @@ func (m *model) fixYPosition() {
}

if m.cursorPosition+1 >= (m.windowHeight-headerHeight)+m.windowYPosition {
m.windowYPosition = m.cursorPosition + 1 - (m.windowHeight - headerHeight)
m.windowYPosition = max(m.cursorPosition+1-(m.windowHeight-headerHeight), 0)
return
}
}
90 changes: 90 additions & 0 deletions search.go
@@ -0,0 +1,90 @@
package fzf

import (
"sort"
"sync"
)

type match struct {
Str string
Index int
MatchedIndexes []int
}

type matches []match

func (m matches) Sort() {
sort.Slice(m, func(i, j int) bool {
mi, mj := m[i].MatchedIndexes, m[j].MatchedIndexes
li, lj := len(mi), len(mj)

if li != lj {
return li < lj
}

for k := 0; k < li; k++ {
if mi[k] != mj[k] {
return mi[k] < mj[k]
}
}

return m[i].Index < m[j].Index
})
}

func fuzzySearch(items *items, search string) matches {
result := make(matches, 0, items.Len())
resultMutex := sync.Mutex{}
wg := sync.WaitGroup{}

numWorkers := 8
chunkSize := (items.Len() + numWorkers - 1) / numWorkers
chunks := make(chan int, numWorkers)

for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()

for start := range chunks {
end := start + chunkSize
if end > items.Len() {
end = items.Len()
}

localMatches := make(matches, 0)

for index := start; index < end; index++ {
item := items.String(index)
matchedIndexes := make([]int, 0, len(search))
j := 0

for i, r := range item {
if j < len(search) && r == rune(search[j]) {
matchedIndexes = append(matchedIndexes, i)
j++
}
}

if j == len(search) {
m := match{Str: item, Index: index, MatchedIndexes: matchedIndexes}
localMatches = append(localMatches, m)
}
}

resultMutex.Lock()
result = append(result, localMatches...)
resultMutex.Unlock()
}
}()
}

for i := 0; i < items.Len(); i += chunkSize {
chunks <- i
}
close(chunks)
wg.Wait()

result.Sort()
return result
}

0 comments on commit c500068

Please sign in to comment.