summaryrefslogtreecommitdiff
path: root/internal/timeline/prune.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/timeline/prune.go')
-rw-r--r--internal/timeline/prune.go74
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
}