From 4d7532f60b1731f0c3a1aa62f50f4b964288e6c1 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 11 May 2024 11:00:42 +0100 Subject: [PATCH] tsdb: reset symbol table for exemplars periodically To avoid keeping the memory alive forever. Signed-off-by: Bryan Boreham --- tsdb/head_dedupelabels.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tsdb/head_dedupelabels.go b/tsdb/head_dedupelabels.go index aaab7c25bec..a16d9072612 100644 --- a/tsdb/head_dedupelabels.go +++ b/tsdb/head_dedupelabels.go @@ -62,6 +62,34 @@ func (h *Head) RebuildSymbolTable(logger log.Logger) *labels.SymbolTable { h.series.locks[i].Unlock() } + type withReset interface{ ResetSymbolTable(*labels.SymbolTable) } + if e, ok := h.exemplars.(withReset); ok { + e.ResetSymbolTable(st) + } level.Info(logger).Log("msg", "RebuildSymbolTable finished", "size", st.Len()) return st } + +func (ce *CircularExemplarStorage) ResetSymbolTable(st *labels.SymbolTable) { + builder := labels.NewScratchBuilderWithSymbolTable(st, 0) + rebuildLabels := func(lbls labels.Labels) labels.Labels { + builder.Reset() + lbls.Range(func(l labels.Label) { + builder.Add(l.Name, l.Value) + }) + return builder.Labels() + } + + ce.lock.RLock() + defer ce.lock.RUnlock() + + for _, v := range ce.index { + v.seriesLabels = rebuildLabels(v.seriesLabels) + } + for i := range ce.exemplars { + if ce.exemplars[i].ref == nil { + continue + } + ce.exemplars[i].exemplar.Labels = rebuildLabels(ce.exemplars[i].exemplar.Labels) + } +}