Less aggressive chunk cache invalidation for --tail

This commit is contained in:
Junegunn Choi 2024-06-10 20:30:19 +09:00
parent dfee7af57b
commit 7fc13c5cfd
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
7 changed files with 32 additions and 17 deletions

View File

@ -1,6 +1,10 @@
CHANGELOG
=========
0.53.1
------
- Bug fixes and minor improvements
0.53.0
------
- Multi-line display

View File

@ -22,6 +22,14 @@ func (cc *ChunkCache) Clear() {
cc.mutex.Unlock()
}
func (cc *ChunkCache) retire(chunk ...*Chunk) {
cc.mutex.Lock()
for _, c := range chunk {
delete(cc.cache, c)
}
cc.mutex.Unlock()
}
// Add adds the list to the cache
func (cc *ChunkCache) Add(chunk *Chunk, key string, list []Result) {
if len(key) == 0 || !chunk.IsFull() || len(list) > queryCacheMax {

View File

@ -16,14 +16,16 @@ type ChunkList struct {
chunks []*Chunk
mutex sync.Mutex
trans ItemBuilder
cache *ChunkCache
}
// NewChunkList returns a new ChunkList
func NewChunkList(trans ItemBuilder) *ChunkList {
func NewChunkList(cache *ChunkCache, trans ItemBuilder) *ChunkList {
return &ChunkList{
chunks: []*Chunk{},
mutex: sync.Mutex{},
trans: trans}
trans: trans,
cache: cache}
}
func (c *Chunk) push(trans ItemBuilder, data []byte) bool {
@ -92,7 +94,9 @@ func (cl *ChunkList) Snapshot(tail int) ([]*Chunk, int, bool) {
// Copy the chunks to keep
ret := make([]*Chunk, numChunks)
copy(ret, cl.chunks[len(cl.chunks)-numChunks:])
minIndex := len(cl.chunks) - numChunks
cl.cache.retire(cl.chunks[:minIndex]...)
copy(ret, cl.chunks[minIndex:])
for left, i := tail, len(ret)-1; i >= 0; i-- {
chunk := ret[i]
@ -104,6 +108,7 @@ func (cl *ChunkList) Snapshot(tail int) ([]*Chunk, int, bool) {
newChunk.items[i] = chunk.items[oldCount-left+i]
}
ret[i] = &newChunk
cl.cache.retire(chunk)
break
}
left -= chunk.count

View File

@ -11,7 +11,7 @@ func TestChunkList(t *testing.T) {
// FIXME global
sortCriteria = []criterion{byScore, byLength}
cl := NewChunkList(func(item *Item, s []byte) bool {
cl := NewChunkList(NewChunkCache(), func(item *Item, s []byte) bool {
item.text = util.ToChars(s)
return true
})
@ -80,7 +80,7 @@ func TestChunkList(t *testing.T) {
}
func TestChunkListTail(t *testing.T) {
cl := NewChunkList(func(item *Item, s []byte) bool {
cl := NewChunkList(NewChunkCache(), func(item *Item, s []byte) bool {
item.text = util.ToChars(s)
return true
})

View File

@ -32,10 +32,6 @@ func (r *revision) bumpMinor() {
r.minor++
}
func (r revision) equals(other revision) bool {
return r.major == other.major && r.minor == other.minor
}
func (r revision) compatible(other revision) bool {
return r.major == other.major
}
@ -94,11 +90,12 @@ func Run(opts *Options) (int, error) {
}
// Chunk list
cache := NewChunkCache()
var chunkList *ChunkList
var itemIndex int32
header := make([]string, 0, opts.HeaderLines)
if len(opts.WithNth) == 0 {
chunkList = NewChunkList(func(item *Item, data []byte) bool {
chunkList = NewChunkList(cache, func(item *Item, data []byte) bool {
if len(header) < opts.HeaderLines {
header = append(header, byteString(data))
eventBox.Set(EvtHeader, header)
@ -110,7 +107,7 @@ func Run(opts *Options) (int, error) {
return true
})
} else {
chunkList = NewChunkList(func(item *Item, data []byte) bool {
chunkList = NewChunkList(cache, func(item *Item, data []byte) bool {
tokens := Tokenize(byteString(data), opts.Delimiter)
if opts.Ansi && opts.Theme.Colored && len(tokens) > 1 {
var ansiState *ansiState
@ -170,7 +167,6 @@ func Run(opts *Options) (int, error) {
forward = true
}
}
cache := NewChunkCache()
patternCache := make(map[string]*Pattern)
patternBuilder := func(runes []rune) *Pattern {
return BuildPattern(cache, patternCache,

View File

@ -87,7 +87,9 @@ func (m *Matcher) Loop() {
m.sort = request.sort
m.revision = request.revision
m.mergerCache = make(map[string]*Merger)
m.cache.Clear()
if !request.revision.compatible(m.revision) {
m.cache.Clear()
}
cacheCleared = true
}
@ -193,7 +195,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
for _, matches := range allMatches {
sliceMatches = append(sliceMatches, matches...)
}
if m.sort {
if m.sort && request.pattern.sortable {
if m.tac {
sort.Sort(ByRelevanceTac(sliceMatches))
} else {
@ -234,7 +236,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
partialResult := <-resultChan
partialResults[partialResult.index] = partialResult.matches
}
return NewMerger(pattern, partialResults, m.sort, m.tac, request.revision, minIndex), false
return NewMerger(pattern, partialResults, m.sort && request.pattern.sortable, m.tac, request.revision, minIndex), false
}
// Reset is called to interrupt/signal the ongoing search
@ -247,7 +249,7 @@ func (m *Matcher) Reset(chunks []*Chunk, patternRunes []rune, cancel bool, final
} else {
event = reqRetry
}
m.reqBox.Set(event, MatchRequest{chunks, pattern, final, sort && pattern.sortable, revision})
m.reqBox.Set(event, MatchRequest{chunks, pattern, final, sort, revision})
}
func (m *Matcher) Stop() {

View File

@ -1174,7 +1174,7 @@ func (t *Terminal) UpdateList(merger *Merger, triggerResultEvent bool) {
}
t.progress = 100
t.merger = merger
if !t.revision.equals(newRevision) {
if t.revision != newRevision {
if !t.revision.compatible(newRevision) {
// Reloaded: clear selection
t.selected = make(map[int32]selectedItem)