From e3a10b327c0d783adca3e76804322d2b98e4465c Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Fri, 18 Mar 2022 17:04:43 +0200 Subject: [PATCH] lib/blockcache: properly remove references to deleted parts Previously references to deleted parts may remain active as cache.m keys. This could prevent from proper memory de-allocation. This could lead to increased memory usage for the following caches starting from v1.73.0: * indexdb/indexBlocks * indexdb/dataBlocks * storage/indexBlocks Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2242 Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2007 This is a follow-up for 88605a7ea22af8684ef03a78a5069ca606bcf35e --- lib/blockcache/blockcache.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/blockcache/blockcache.go b/lib/blockcache/blockcache.go index 86727e353..b4911ebef 100644 --- a/lib/blockcache/blockcache.go +++ b/lib/blockcache/blockcache.go @@ -265,14 +265,10 @@ func (c *cache) cleanByTimeout() { defer c.mu.Unlock() for len(c.lah) > 0 { - e := c.lah[0] - if lastAccessTime < e.lastAccessTime { + if lastAccessTime < c.lah[0].lastAccessTime { break } - c.updateSizeBytes(-e.b.SizeBytes()) - pes := c.m[e.k.Part] - delete(pes, e.k.Offset) - heap.Pop(&c.lah) + c.removeLeastRecentlyAccessedItem() } } @@ -333,14 +329,23 @@ func (c *cache) PutBlock(k Key, b Block) { c.updateSizeBytes(e.b.SizeBytes()) maxSizeBytes := c.getMaxSizeBytes() for c.SizeBytes() > maxSizeBytes && len(c.lah) > 0 { - e := c.lah[0] - c.updateSizeBytes(-e.b.SizeBytes()) - pes := c.m[e.k.Part] - delete(pes, e.k.Offset) - heap.Pop(&c.lah) + c.removeLeastRecentlyAccessedItem() } } +func (c *cache) removeLeastRecentlyAccessedItem() { + e := c.lah[0] + c.updateSizeBytes(-e.b.SizeBytes()) + p := e.k.Part + pes := c.m[p] + delete(pes, e.k.Offset) + if len(pes) == 0 { + // Remove reference to p from c.m in order to free up memory occupied by p. + delete(c.m, p) + } + heap.Pop(&c.lah) +} + func (c *cache) Len() int { c.mu.Lock() defer c.mu.Unlock()