diff options
Diffstat (limited to 'internal/timeline/prune.go')
-rw-r--r-- | internal/timeline/prune.go | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/internal/timeline/prune.go b/internal/timeline/prune.go index 8360032b7..a3a5bf9cb 100644 --- a/internal/timeline/prune.go +++ b/internal/timeline/prune.go @@ -21,47 +21,63 @@ import ( "container/list" ) -const ( - defaultDesiredIndexedItemsLength = 400 - defaultDesiredPreparedItemsLength = 50 -) - func (t *timeline) Prune(desiredPreparedItemsLength int, desiredIndexedItemsLength int) int { t.Lock() defer t.Unlock() - pruneList := func(pruneTo int, listToPrune *list.List) int { - if listToPrune == nil { - // no need to prune - return 0 - } + l := t.items.data + if l == nil { + // Nothing to prune. + return 0 + } - unprunedLength := listToPrune.Len() - if unprunedLength <= pruneTo { - // no need to prune - return 0 - } + var ( + position int + totalPruned int + toRemove *[]*list.Element + ) + + // Only initialize toRemove if we know we're + // going to need it, otherwise skiperino. + if toRemoveLen := t.items.data.Len() - desiredIndexedItemsLength; toRemoveLen > 0 { + toRemove = func() *[]*list.Element { tr := make([]*list.Element, 0, toRemoveLen); return &tr }() + } + + // Work from the front of the list until we get + // to the point where we need to start pruning. + for e := l.Front(); e != nil; e = e.Next() { + position++ - // work from the back + assemble a slice of entries that we will prune - amountStillToPrune := unprunedLength - pruneTo - itemsToPrune := make([]*list.Element, 0, amountStillToPrune) - for e := listToPrune.Back(); amountStillToPrune > 0; e = e.Prev() { - itemsToPrune = append(itemsToPrune, e) - amountStillToPrune-- + if position <= desiredPreparedItemsLength { + // We're still within our allotted + // prepped length, nothing to do yet. + continue } - // remove the entries we found - var totalPruned int - for _, e := range itemsToPrune { - listToPrune.Remove(e) + // We need to *at least* unprepare this entry. + // If we're beyond our indexed length already, + // we can just remove the item completely. + if position > desiredIndexedItemsLength { + *toRemove = append(*toRemove, e) totalPruned++ + continue + } + + entry := e.Value.(*indexedItemsEntry) //nolint:forcetypeassert + if entry.prepared == nil { + // It's already unprepared (mood). + continue } - return totalPruned + entry.prepared = nil // <- eat this up please garbage collector nom nom nom + totalPruned++ } - prunedPrepared := pruneList(desiredPreparedItemsLength, t.preparedItems.data) - prunedIndexed := pruneList(desiredIndexedItemsLength, t.indexedItems.data) + if toRemove != nil { + for _, e := range *toRemove { + l.Remove(e) + } + } - return prunedPrepared + prunedIndexed + return totalPruned } |