Skip to content

Commit

Permalink
compactor: avoid memory blow-up with stringlabels
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
bboreham committed Jul 29, 2023
1 parent 2a075ce commit 4bfa99a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
10 changes: 10 additions & 0 deletions tsdb/addsymbol.go
Original file line number Diff line number Diff line change
@@ -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)
}
15 changes: 15 additions & 0 deletions tsdb/addsymbol_stringlabels.go
Original file line number Diff line number Diff line change
@@ -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)
}
5 changes: 0 additions & 5 deletions tsdb/symbols_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4bfa99a

Please sign in to comment.