Skip to content

Commit 220249f

Browse files
authored
lib/storage: use lrucache to implement tagFilters loops cache
The tagFilters loop cache is per-indexDB which means that currently there are two instances, one for idbCurr and one for idbPrev. When the partition index (#8134) is released, there will be as many instances of this cache as there will be partitions. The cache is implemented using workingsetcache. Which occupies at least 30MB even when unused. Given that only the latest indexDB is used most of the time, a lot of memory can be wasted. Therefore the cache implementation is changed to lrucache because it does not consume memory when it is unused and also has timeout-based eviction. This is a follow-up for 4cd727a (VictoriaMetrics/VictoriaMetrics#10072).
1 parent c6731f9 commit 220249f

File tree

1 file changed

+28
-18
lines changed

1 file changed

+28
-18
lines changed

lib/storage/index_db.go

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/VictoriaMetrics/VictoriaMetrics/lib/querytracer"
3232
"github.com/VictoriaMetrics/VictoriaMetrics/lib/slicesutil"
3333
"github.com/VictoriaMetrics/VictoriaMetrics/lib/uint64set"
34-
"github.com/VictoriaMetrics/VictoriaMetrics/lib/workingsetcache"
3534
)
3635

3736
const (
@@ -134,7 +133,7 @@ type indexDB struct {
134133

135134
// Cache for (date, tagFilter) -> loopsCount, which is used for reducing
136135
// the amount of work when matching a set of filters.
137-
loopsPerDateTagFilterCache *workingsetcache.Cache
136+
loopsPerDateTagFilterCache *lrucache.Cache
138137

139138
// dateMetricIDCache is (date, metricID) cache that is used to speed up the
140139
// data ingestion by storing the is.hasDateMetricID() search results in
@@ -158,6 +157,10 @@ func getTagFiltersCacheSize() uint64 {
158157
return maxTagFiltersCacheSize
159158
}
160159

160+
func getTagFiltersLoopsCacheSize() uint64 {
161+
return uint64(float64(memory.Allowed()) / 128)
162+
}
163+
161164
// mustOpenIndexDB opens index db from the given path.
162165
//
163166
// The last segment of the path should contain unique hex value which
@@ -183,7 +186,7 @@ func mustOpenIndexDB(path string, s *Storage, isReadOnly *atomic.Bool, noRegiste
183186
minMissingTimestampByKey: make(map[string]int64),
184187
tagFiltersToMetricIDsCache: tfssCache,
185188
s: s,
186-
loopsPerDateTagFilterCache: workingsetcache.New(memory.Allowed() / 128),
189+
loopsPerDateTagFilterCache: lrucache.NewCache(getTagFiltersLoopsCacheSize),
187190
dateMetricIDCache: newDateMetricIDCache(),
188191
}
189192
db.noRegisterNewSeries.Store(noRegisterNewSeries)
@@ -298,13 +301,13 @@ func (db *indexDB) decRef() {
298301
tbPath := db.tb.Path()
299302
db.tb.MustClose()
300303
db.tb = nil
304+
db.s = nil
301305

302306
// Free space occupied by caches owned by db.
303307
db.tagFiltersToMetricIDsCache.MustStop()
304-
db.loopsPerDateTagFilterCache.Stop()
308+
db.loopsPerDateTagFilterCache.MustStop()
305309

306310
db.tagFiltersToMetricIDsCache = nil
307-
db.s = nil
308311
db.loopsPerDateTagFilterCache = nil
309312

310313
if !db.mustDrop.Load() {
@@ -2974,25 +2977,32 @@ func (is *indexSearch) getLoopsCountAndTimestampForDateFilter(date uint64, tf *t
29742977
is.kb.B = appendDateTagFilterCacheKey(is.kb.B[:0], is.db.name, date, tf)
29752978
kb := kbPool.Get()
29762979
defer kbPool.Put(kb)
2977-
kb.B = is.db.loopsPerDateTagFilterCache.Get(kb.B[:0], is.kb.B)
2978-
if len(kb.B) != 3*8 {
2980+
e := is.db.loopsPerDateTagFilterCache.GetEntry(bytesutil.ToUnsafeString(is.kb.B))
2981+
if e == nil {
29792982
return 0, 0, 0
29802983
}
2981-
loopsCount := encoding.UnmarshalInt64(kb.B)
2982-
filterLoopsCount := encoding.UnmarshalInt64(kb.B[8:])
2983-
timestamp := encoding.UnmarshalUint64(kb.B[16:])
2984-
return loopsCount, filterLoopsCount, timestamp
2984+
v := e.(*tagFiltersLoops)
2985+
return v.loopsCount, v.filterLoopsCount, v.timestamp
2986+
}
2987+
2988+
type tagFiltersLoops struct {
2989+
loopsCount int64
2990+
filterLoopsCount int64
2991+
timestamp uint64
2992+
}
2993+
2994+
func (v *tagFiltersLoops) SizeBytes() uint64 {
2995+
return uint64(unsafe.Sizeof(*v))
29852996
}
29862997

29872998
func (is *indexSearch) storeLoopsCountForDateFilter(date uint64, tf *tagFilter, loopsCount, filterLoopsCount int64) {
2988-
currentTimestamp := fasttime.UnixTimestamp()
2999+
v := tagFiltersLoops{
3000+
loopsCount: loopsCount,
3001+
filterLoopsCount: filterLoopsCount,
3002+
timestamp: fasttime.UnixTimestamp(),
3003+
}
29893004
is.kb.B = appendDateTagFilterCacheKey(is.kb.B[:0], is.db.name, date, tf)
2990-
kb := kbPool.Get()
2991-
kb.B = encoding.MarshalInt64(kb.B[:0], loopsCount)
2992-
kb.B = encoding.MarshalInt64(kb.B, filterLoopsCount)
2993-
kb.B = encoding.MarshalUint64(kb.B, currentTimestamp)
2994-
is.db.loopsPerDateTagFilterCache.Set(is.kb.B, kb.B)
2995-
kbPool.Put(kb)
3005+
is.db.loopsPerDateTagFilterCache.PutEntry(string(is.kb.B), &v)
29963006
}
29973007

29983008
func appendDateTagFilterCacheKey(dst []byte, indexDBName string, date uint64, tf *tagFilter) []byte {

0 commit comments

Comments
 (0)