mirror of
https://github.com/prometheus/prometheus.git
synced 2026-06-04 14:12:14 -04:00
chore: cleanup tsdb/chunkenc benchmarking suite
Signed-off-by: bwplotka <bwplotka@gmail.com>
This commit is contained in:
parent
30992dd032
commit
968b85e1cc
2 changed files with 228 additions and 109 deletions
228
tsdb/chunkenc/benchmark_test.go
Normal file
228
tsdb/chunkenc/benchmark_test.go
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
package chunkenc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/model/histogram"
|
||||
)
|
||||
|
||||
/*
|
||||
export bench=chunkenc && go test \
|
||||
-run '^$' -bench '^BenchmarkChunkEnc' \
|
||||
-benchtime 5s -count 6 -cpu 2 -timeout 999m \
|
||||
| tee ${bench}.txt
|
||||
*/
|
||||
func BenchmarkChunkEnc(b *testing.B) {
|
||||
r := rand.New(rand.NewSource(1))
|
||||
|
||||
for _, data := range []struct {
|
||||
name string
|
||||
deltas func() (int64, float64)
|
||||
}{
|
||||
{
|
||||
name: "constant",
|
||||
deltas: func() (int64, float64) {
|
||||
return 1000, 0
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "random steps",
|
||||
deltas: func() (int64, float64) {
|
||||
return int64(r.Intn(100) - 50 + 15000), // 15 seconds +- up to 100ms of jitter.
|
||||
float64(r.Intn(100) - 50) // Varying from -50 to +50 in 100 discrete steps.
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "random 0-1",
|
||||
deltas: func() (int64, float64) {
|
||||
return int64(r.Intn(100) - 50 + 15000), // 15 seconds +- up to 100ms of jitter.
|
||||
r.Float64() // Random between 0 and 1.0.
|
||||
},
|
||||
},
|
||||
} {
|
||||
b.Run("data="+data.name, func(b *testing.B) {
|
||||
b.Run("format=XOR", func(b *testing.B) {
|
||||
benchmarkChunkEnc(b, data.deltas, func() Chunk { return NewXORChunk() })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkChunkEnc(b *testing.B, deltas func() (int64, float64), newChunk func() Chunk) {
|
||||
var (
|
||||
t = int64(1234123324)
|
||||
v = 1243535.123
|
||||
)
|
||||
const nSamples = 120 // Same as tsdb.DefaultSamplesPerChunk.
|
||||
var samples []pair
|
||||
for range nSamples {
|
||||
dt, dv := deltas()
|
||||
t += dt
|
||||
v += dv
|
||||
samples = append(samples, pair{t: t, v: v})
|
||||
}
|
||||
|
||||
// Measure encoding efficiency.
|
||||
b.Run("op=Append", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
for b.Loop() {
|
||||
c := newChunk()
|
||||
|
||||
a, err := c.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
for _, p := range samples {
|
||||
a.Append(p.t, p.v)
|
||||
}
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
}
|
||||
})
|
||||
|
||||
// Create a chunk for decoding and compact benchmarks.
|
||||
c := newChunk()
|
||||
a, err := c.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
for _, p := range samples {
|
||||
a.Append(p.t, p.v)
|
||||
}
|
||||
|
||||
// Measure decoding efficiency.
|
||||
b.Run("op=Iterate", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
var (
|
||||
sink float64
|
||||
it Iterator
|
||||
)
|
||||
for i := 0; b.Loop(); {
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
|
||||
it := c.Iterator(it)
|
||||
for it.Next() == ValFloat {
|
||||
_, v := it.At()
|
||||
sink = v
|
||||
i++
|
||||
}
|
||||
if err := it.Err(); err != nil && !errors.Is(err, io.EOF) {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
_ = sink
|
||||
}
|
||||
})
|
||||
|
||||
// Measure size before and after compaction and it's efficiency.
|
||||
b.Run("op=Compact", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
c.Compact()
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/compacted_chunk")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
export bench=histchunkenc && go test \
|
||||
-run '^$' -bench '^BenchmarkHistogramChunkEnc' \
|
||||
-benchtime 5s -count 6 -cpu 2 -timeout 999m \
|
||||
| tee ${bench}.txt
|
||||
*/
|
||||
func BenchmarkHistogramChunkEnc(b *testing.B) {
|
||||
// Create a histogram with a bunch of spans and buckets.
|
||||
const (
|
||||
numSpans = 1000
|
||||
spanLength = 10
|
||||
)
|
||||
h := &histogram.Histogram{
|
||||
Schema: 0,
|
||||
Count: 100,
|
||||
Sum: 1000,
|
||||
ZeroThreshold: 0.001,
|
||||
ZeroCount: 5,
|
||||
}
|
||||
for range numSpans {
|
||||
h.PositiveSpans = append(h.PositiveSpans, histogram.Span{Offset: 5, Length: spanLength})
|
||||
h.NegativeSpans = append(h.NegativeSpans, histogram.Span{Offset: 5, Length: spanLength})
|
||||
for j := range spanLength {
|
||||
h.PositiveBuckets = append(h.PositiveBuckets, int64(j))
|
||||
h.NegativeBuckets = append(h.NegativeBuckets, int64(j))
|
||||
}
|
||||
}
|
||||
|
||||
// Measure encoding efficiency.
|
||||
b.Run("op=Append", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
for b.Loop() {
|
||||
c := Chunk(NewHistogramChunk())
|
||||
|
||||
a, err := c.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
var stop bool
|
||||
for i := int64(0); !stop; i++ {
|
||||
_, stop, _, err = a.AppendHistogram(nil, i, h, true)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
}
|
||||
})
|
||||
|
||||
// Create a chunk for decoding and compact benchmarks.
|
||||
c := Chunk(NewHistogramChunk())
|
||||
a, err := c.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
var stop bool
|
||||
for i := int64(0); !stop; i++ {
|
||||
_, stop, _, err = a.AppendHistogram(nil, i, h, true)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Measure decoding efficiency.
|
||||
b.Run("op=Iterate", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
var (
|
||||
sink *histogram.Histogram
|
||||
it Iterator
|
||||
)
|
||||
for i := 0; b.Loop(); {
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
|
||||
it := c.Iterator(it)
|
||||
for it.Next() == ValFloat {
|
||||
_, got := it.AtHistogram(h)
|
||||
sink = got
|
||||
i++
|
||||
}
|
||||
if err := it.Err(); err != nil && !errors.Is(err, io.EOF) {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
_ = sink
|
||||
}
|
||||
})
|
||||
|
||||
// Measure size before and after compaction and it's efficiency.
|
||||
b.Run("op=Compact", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/chunk")
|
||||
c.Compact()
|
||||
b.ReportMetric(float64(len(c.Bytes())), "B/compacted_chunk")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ package chunkenc
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
|
|
@ -199,111 +198,3 @@ func (c fakeChunk) Encoding() Encoding {
|
|||
func (c fakeChunk) Reset([]byte) {
|
||||
c.t.Fatal("Reset should not be called")
|
||||
}
|
||||
|
||||
func benchmarkIterator(b *testing.B, newChunk func() Chunk) {
|
||||
const samplesPerChunk = 250
|
||||
var (
|
||||
t = int64(1234123324)
|
||||
v = 1243535.123
|
||||
exp []pair
|
||||
)
|
||||
for range samplesPerChunk {
|
||||
// t += int64(rand.Intn(10000) + 1)
|
||||
t += int64(1000)
|
||||
// v = rand.Float64()
|
||||
v += float64(100)
|
||||
exp = append(exp, pair{t: t, v: v})
|
||||
}
|
||||
|
||||
chunk := newChunk()
|
||||
{
|
||||
a, err := chunk.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
j := 0
|
||||
for _, p := range exp {
|
||||
if j > 250 {
|
||||
break
|
||||
}
|
||||
a.Append(p.t, p.v)
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
|
||||
var res float64
|
||||
var it Iterator
|
||||
for i := 0; b.Loop(); {
|
||||
it := chunk.Iterator(it)
|
||||
|
||||
for it.Next() == ValFloat {
|
||||
_, v := it.At()
|
||||
res = v
|
||||
i++
|
||||
}
|
||||
if err := it.Err(); err != nil && !errors.Is(err, io.EOF) {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
_ = res
|
||||
}
|
||||
}
|
||||
|
||||
func newXORChunk() Chunk {
|
||||
return NewXORChunk()
|
||||
}
|
||||
|
||||
func BenchmarkXORIterator(b *testing.B) {
|
||||
benchmarkIterator(b, newXORChunk)
|
||||
}
|
||||
|
||||
func BenchmarkXORAppender(b *testing.B) {
|
||||
r := rand.New(rand.NewSource(1))
|
||||
b.Run("constant", func(b *testing.B) {
|
||||
benchmarkAppender(b, func() (int64, float64) {
|
||||
return 1000, 0
|
||||
}, newXORChunk)
|
||||
})
|
||||
b.Run("random steps", func(b *testing.B) {
|
||||
benchmarkAppender(b, func() (int64, float64) {
|
||||
return int64(r.Intn(100) - 50 + 15000), // 15 seconds +- up to 100ms of jitter.
|
||||
float64(r.Intn(100) - 50) // Varying from -50 to +50 in 100 discrete steps.
|
||||
}, newXORChunk)
|
||||
})
|
||||
b.Run("random 0-1", func(b *testing.B) {
|
||||
benchmarkAppender(b, func() (int64, float64) {
|
||||
return int64(r.Intn(100) - 50 + 15000), // 15 seconds +- up to 100ms of jitter.
|
||||
r.Float64() // Random between 0 and 1.0.
|
||||
}, newXORChunk)
|
||||
})
|
||||
}
|
||||
|
||||
func benchmarkAppender(b *testing.B, deltas func() (int64, float64), newChunk func() Chunk) {
|
||||
var (
|
||||
t = int64(1234123324)
|
||||
v = 1243535.123
|
||||
)
|
||||
const nSamples = 120 // Same as tsdb.DefaultSamplesPerChunk.
|
||||
var exp []pair
|
||||
for range nSamples {
|
||||
dt, dv := deltas()
|
||||
t += dt
|
||||
v += dv
|
||||
exp = append(exp, pair{t: t, v: v})
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
|
||||
for b.Loop() {
|
||||
c := newChunk()
|
||||
|
||||
a, err := c.Appender()
|
||||
if err != nil {
|
||||
b.Fatalf("get appender: %s", err)
|
||||
}
|
||||
for _, p := range exp {
|
||||
a.Append(p.t, p.v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue