perf(tsdb): reuse map of sample types to speed up head appender

While investigating +10% CPU in v3.7 release, found that ~5% is from
expanding the types map. Try reuse.

Also fix a linter error.

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
György Krajcsovits 2025-10-06 21:44:34 +02:00
parent fe11cae637
commit c26a5390aa
No known key found for this signature in database
GPG Key ID: 47A8F9CE80FD7C7F
3 changed files with 22 additions and 2 deletions

View File

@ -93,6 +93,7 @@ type Head struct {
floatHistogramsPool zeropool.Pool[[]record.RefFloatHistogramSample]
metadataPool zeropool.Pool[[]record.RefMetadata]
seriesPool zeropool.Pool[[]*memSeries]
typeMapPool zeropool.Pool[map[chunks.HeadSeriesRef]sampleType]
bytesPool zeropool.Pool[[]byte]
memChunkPool sync.Pool

View File

@ -173,7 +173,7 @@ func (h *Head) appender() *headAppender {
oooTimeWindow: h.opts.OutOfOrderTimeWindow.Load(),
seriesRefs: h.getRefSeriesBuffer(),
series: h.getSeriesBuffer(),
typesInBatch: map[chunks.HeadSeriesRef]sampleType{},
typesInBatch: h.getTypeMap(),
appendID: appendID,
cleanupAppendIDsBelow: cleanupAppendIDsBelow,
}
@ -297,6 +297,19 @@ func (h *Head) putSeriesBuffer(b []*memSeries) {
h.seriesPool.Put(b[:0])
}
func (h *Head) getTypeMap() map[chunks.HeadSeriesRef]sampleType {
b := h.typeMapPool.Get()
if b == nil {
return make(map[chunks.HeadSeriesRef]sampleType)
}
return b
}
func (h *Head) putTypeMap(b map[chunks.HeadSeriesRef]sampleType) {
clear(b)
h.typeMapPool.Put(b)
}
func (h *Head) getBytesBuffer() []byte {
b := h.bytesPool.Get()
if b == nil {
@ -1687,8 +1700,13 @@ func (a *headAppender) Commit() (err error) {
h := a.head
defer func() {
if a.closed {
// Don't double-close in case Rollback() was called.
return
}
h.putRefSeriesBuffer(a.seriesRefs)
h.putSeriesBuffer(a.series)
h.putTypeMap(a.typesInBatch)
a.closed = true
}()
@ -2216,6 +2234,7 @@ func (a *headAppender) Rollback() (err error) {
a.closed = true
h.putRefSeriesBuffer(a.seriesRefs)
h.putSeriesBuffer(a.series)
h.putTypeMap(a.typesInBatch)
}()
var series *memSeries

View File

@ -19,7 +19,7 @@ import (
"testing"
)
func Test(t *testing.T, f func(t *testing.T)) {
func Test(t *testing.T, _ func(t *testing.T)) {
t.Skip("goexperiment.synctest is not enabled")
}