From 9161f9d2e1b4a78de3796c8dac2a729176524772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Mon, 24 Jan 2022 14:39:26 +0100 Subject: [PATCH] prometheus: added json-loading benchmark (#44309) --- pkg/tsdb/prometheus/prometeus_bench_test.go | 82 +++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 pkg/tsdb/prometheus/prometeus_bench_test.go diff --git a/pkg/tsdb/prometheus/prometeus_bench_test.go b/pkg/tsdb/prometheus/prometeus_bench_test.go new file mode 100644 index 00000000000..b7365e30c44 --- /dev/null +++ b/pkg/tsdb/prometheus/prometeus_bench_test.go @@ -0,0 +1,82 @@ +package prometheus + +import ( + "context" + "fmt" + "math/rand" + "strings" + "testing" + "time" + + "github.com/grafana/grafana/pkg/infra/tracing" + "github.com/stretchr/testify/require" +) + +// when memory-profiling this benchmark, these commands are recommended: +// - go test -benchmem -run=^$ -benchtime 1x -memprofile memprofile.out -memprofilerate 1 -bench ^BenchmarkJson$ github.com/grafana/grafana/pkg/tsdb/prometheus +// - go tool pprof -http=localhost:6061 memprofile.out +func BenchmarkJson(b *testing.B) { + resp, query := createJsonTestData(1642000000, 1, 300, 400) + + api, err := makeMockedApi(resp) + require.NoError(b, err) + + tracer, err := tracing.InitializeTracerForTest() + require.NoError(b, err) + + s := Service{tracer: tracer} + + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, _ = s.runQueries(context.Background(), api, []*PrometheusQuery{&query}) + } +} + +const nanRate = 0.002 + +// we build the JSON file from strings, +// it was easier to write it this way. +func makeJsonTestMetric(index int) string { + return fmt.Sprintf(`{"server":"main","category":"maintenance","case":"%v"}`, index) +} + +// return a value between -100 and +100, sometimes NaN, in string +func makeJsonTestValue(r *rand.Rand) string { + if r.Float64() < nanRate { + return "NaN" + } else { + return fmt.Sprintf("%f", (r.Float64()*200)-100) + } +} + +// create one time-series +func makeJsonTestSeries(start int64, step int64, timestampCount int, r *rand.Rand, seriesIndex int) string { + var values []string + for i := 0; i < timestampCount; i++ { + value := fmt.Sprintf(`[%d,"%v"]`, start+(int64(i)*step), makeJsonTestValue(r)) + values = append(values, value) + } + return fmt.Sprintf(`{"metric":%v,"values":[%v]}`, makeJsonTestMetric(seriesIndex), strings.Join(values, ",")) +} + +func createJsonTestData(start int64, step int64, timestampCount int, seriesCount int) ([]byte, PrometheusQuery) { + // we use random numbers as values, but they have to be the same numbers + // every time we call this, so we create a random source. + r := rand.New(rand.NewSource(42)) + var allSeries []string + for i := 0; i < seriesCount; i++ { + allSeries = append(allSeries, makeJsonTestSeries(start, step, timestampCount, r, i)) + } + bytes := []byte(fmt.Sprintf(`{"data":{"resultType":"matrix","result":[%v]},"status":"success"}`, strings.Join(allSeries, ","))) + + query := PrometheusQuery{ + RefId: "A", + RangeQuery: true, + Start: time.Unix(start, 0), + End: time.Unix(start+((int64(timestampCount)-1)*step), 0), + Step: time.Second * time.Duration(step), + Expr: "test", + } + + return bytes, query +}