From 848df13d3aad0e81882b2384e0fe3040b96df46f Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 16 Apr 2025 17:55:45 +0100 Subject: [PATCH 1/2] [TESTS] Faster WAL Benchmarks by reusing buffer Less garbage collection. Signed-off-by: Bryan Boreham --- tsdb/head_test.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tsdb/head_test.go b/tsdb/head_test.go index 8cd44db841..1bf4225e17 100644 --- a/tsdb/head_test.go +++ b/tsdb/head_test.go @@ -149,24 +149,29 @@ func BenchmarkHeadAppender_Append_Commit_ExistingSeries(b *testing.B) { } } -func populateTestWL(t testing.TB, w *wlog.WL, recs []interface{}) { +func populateTestWL(t testing.TB, w *wlog.WL, recs []interface{}, buf []byte) []byte { var enc record.Encoder for _, r := range recs { + buf = buf[:0] switch v := r.(type) { case []record.RefSeries: - require.NoError(t, w.Log(enc.Series(v, nil))) + buf = enc.Series(v, buf) case []record.RefSample: - require.NoError(t, w.Log(enc.Samples(v, nil))) + buf = enc.Samples(v, buf) case []tombstones.Stone: - require.NoError(t, w.Log(enc.Tombstones(v, nil))) + buf = enc.Tombstones(v, buf) case []record.RefExemplar: - require.NoError(t, w.Log(enc.Exemplars(v, nil))) + buf = enc.Exemplars(v, buf) case []record.RefMmapMarker: - require.NoError(t, w.Log(enc.MmapMarkers(v, nil))) + buf = enc.MmapMarkers(v, buf) case []record.RefMetadata: - require.NoError(t, w.Log(enc.Metadata(v, nil))) + buf = enc.Metadata(v, buf) + default: + continue } + require.NoError(t, w.Log(buf)) } + return buf } func readTestWAL(t testing.TB, dir string) (recs []interface{}) { @@ -309,6 +314,7 @@ func BenchmarkLoadWLs(b *testing.B) { // Write series. refSeries := make([]record.RefSeries, 0, c.seriesPerBatch) + var buf []byte for k := 0; k < c.batches; k++ { refSeries = refSeries[:0] for i := k * c.seriesPerBatch; i < (k+1)*c.seriesPerBatch; i++ { @@ -333,7 +339,7 @@ func BenchmarkLoadWLs(b *testing.B) { writeSeries = newWriteSeries } - populateTestWL(b, wal, []interface{}{writeSeries}) + buf = populateTestWL(b, wal, []interface{}{writeSeries}, buf) } // Write samples. @@ -359,7 +365,7 @@ func BenchmarkLoadWLs(b *testing.B) { V: float64(i) * 100, }) } - populateTestWL(b, wal, []interface{}{refSamples}) + buf = populateTestWL(b, wal, []interface{}{refSamples}, buf) } } @@ -398,7 +404,7 @@ func BenchmarkLoadWLs(b *testing.B) { Labels: labels.FromStrings("trace_id", fmt.Sprintf("trace-%d", i)), }) } - populateTestWL(b, wal, []interface{}{refExemplars}) + buf = populateTestWL(b, wal, []interface{}{refExemplars}, buf) } } @@ -427,10 +433,10 @@ func BenchmarkLoadWLs(b *testing.B) { }) } if shouldAddMarkers { - populateTestWL(b, wbl, []interface{}{refMarkers}) + populateTestWL(b, wbl, []interface{}{refMarkers}, buf) } - populateTestWL(b, wal, []interface{}{refSamples}) - populateTestWL(b, wbl, []interface{}{refSamples}) + buf = populateTestWL(b, wal, []interface{}{refSamples}, buf) + buf = populateTestWL(b, wbl, []interface{}{refSamples}, buf) } } @@ -739,7 +745,7 @@ func TestHead_ReadWAL(t *testing.T) { require.NoError(t, head.Close()) }() - populateTestWL(t, w, entries) + populateTestWL(t, w, entries, nil) require.NoError(t, head.Init(math.MinInt64)) require.Equal(t, uint64(101), head.lastSeriesID.Load()) @@ -1383,7 +1389,7 @@ func TestHeadDeleteSeriesWithoutSamples(t *testing.T) { require.NoError(t, head.Close()) }() - populateTestWL(t, w, entries) + populateTestWL(t, w, entries, nil) require.NoError(t, head.Init(math.MinInt64)) From 1d4b1d76a5aa43e3f12579a3404cd49bc199476c Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 16 Apr 2025 18:02:47 +0100 Subject: [PATCH 2/2] [TESTS] More efficient label creation in BenchmarkLoadWLs Use the Builder abstraction instead of going via a map. Signed-off-by: Bryan Boreham --- tsdb/head_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tsdb/head_test.go b/tsdb/head_test.go index 1bf4225e17..74b5887da1 100644 --- a/tsdb/head_test.go +++ b/tsdb/head_test.go @@ -315,15 +315,15 @@ func BenchmarkLoadWLs(b *testing.B) { // Write series. refSeries := make([]record.RefSeries, 0, c.seriesPerBatch) var buf []byte + builder := labels.NewBuilder(labels.EmptyLabels()) + for j := 1; j < labelsPerSeries; j++ { + builder.Set(defaultLabelName+strconv.Itoa(j), defaultLabelValue+strconv.Itoa(j)) + } for k := 0; k < c.batches; k++ { refSeries = refSeries[:0] for i := k * c.seriesPerBatch; i < (k+1)*c.seriesPerBatch; i++ { - lbls := make(map[string]string, labelsPerSeries) - lbls[defaultLabelName] = strconv.Itoa(i) - for j := 1; len(lbls) < labelsPerSeries; j++ { - lbls[defaultLabelName+strconv.Itoa(j)] = defaultLabelValue + strconv.Itoa(j) - } - refSeries = append(refSeries, record.RefSeries{Ref: chunks.HeadSeriesRef(i) * 101, Labels: labels.FromMap(lbls)}) + builder.Set(defaultLabelName, strconv.Itoa(i)) + refSeries = append(refSeries, record.RefSeries{Ref: chunks.HeadSeriesRef(i) * 101, Labels: builder.Labels()}) } writeSeries := refSeries