From 4ced6d5f40973fccb0d0dddfb843aa2085d160f2 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 29 Jul 2023 10:12:09 +0100 Subject: [PATCH] compactor: avoid memory blow-up with stringlabels When compiled with `-tags stringlabels`, the names and values point into a larger block of memory containing all labels. Garbage-collection considers the entire block "live" if you point to a part of it, so the map ends up retaining all labels for (nearly) all series. Cloning the string value avoids this problem, and we check first if the value is already in the map. Since the clone is more expensive, only do it when built with `-tags stringlabels`. Signed-off-by: Bryan Boreham --- tsdb/addsymbol.go | 10 ++++++++++ tsdb/addsymbol_stringlabels.go | 15 +++++++++++++++ tsdb/symbols_batch.go | 5 ----- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 tsdb/addsymbol.go create mode 100644 tsdb/addsymbol_stringlabels.go diff --git a/tsdb/addsymbol.go b/tsdb/addsymbol.go new file mode 100644 index 000000000..e6046c5ed --- /dev/null +++ b/tsdb/addsymbol.go @@ -0,0 +1,10 @@ +//go:build !stringlabels + +// Split out function which needs to be coded differently for stringlabels case. + +package tsdb + +func (sw *symbolsBatcher) addSymbol(sym string) error { + sw.buffer[sym] = struct{}{} + return sw.flushSymbols(false) +} diff --git a/tsdb/addsymbol_stringlabels.go b/tsdb/addsymbol_stringlabels.go new file mode 100644 index 000000000..86f19c847 --- /dev/null +++ b/tsdb/addsymbol_stringlabels.go @@ -0,0 +1,15 @@ +//go:build stringlabels + +// Split out function which needs to be coded differently for stringlabels case. + +package tsdb + +import "strings" + +func (sw *symbolsBatcher) addSymbol(sym string) error { + if _, found := sw.buffer[sym]; !found { + sym = strings.Clone(sym) // So we don't retain reference to the entire labels block. + sw.buffer[sym] = struct{}{} + } + return sw.flushSymbols(false) +} diff --git a/tsdb/symbols_batch.go b/tsdb/symbols_batch.go index 13fe84f90..4ecc66bf0 100644 --- a/tsdb/symbols_batch.go +++ b/tsdb/symbols_batch.go @@ -145,11 +145,6 @@ func newSymbolsBatcher(limit int, dir string, flushers *symbolFlushers) *symbols } } -func (sw *symbolsBatcher) addSymbol(sym string) error { - sw.buffer[sym] = struct{}{} - return sw.flushSymbols(false) -} - func (sw *symbolsBatcher) flushSymbols(force bool) error { if !force && len(sw.buffer) < sw.limit { return nil