diff --git a/expfmt/benchmark_test.go b/expfmt/benchmark_test.go new file mode 100644 index 00000000..a6937880 --- /dev/null +++ b/expfmt/benchmark_test.go @@ -0,0 +1,213 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package expfmt + +import ( + "bytes" + "math" + "testing" + + dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func benchmarkMetricFamilies() []*dto.MetricFamily { + return []*dto.MetricFamily{ + { + Name: proto.String("network_transmit_bytes_total"), + Help: proto.String("Total number of bytes transmitted over the network."), + Type: dto.MetricType_COUNTER.Enum(), + Unit: proto.String("bytes"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("device"), Value: proto.String("eth0")}, + }, + Counter: &dto.Counter{ + Value: proto.Float64(1024), + CreatedTimestamp: ×tamppb.Timestamp{Seconds: 1234567890}, + Exemplar: &dto.Exemplar{ + Label: []*dto.LabelPair{ + {Name: proto.String("trace_id"), Value: proto.String("1234567890abcdef")}, + }, + Value: proto.Float64(512), + Timestamp: ×tamppb.Timestamp{Seconds: 1234567890, Nanos: 500000000}, + }, + }, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + { + Name: proto.String("process_cpu_seconds_total"), + Help: proto.String("Total user and system CPU time spent in seconds."), + Type: dto.MetricType_GAUGE.Enum(), + Unit: proto.String("seconds"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("mode"), Value: proto.String("user")}, + }, + Gauge: &dto.Gauge{Value: proto.Float64(123.45)}, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + { + Name: proto.String("memory_free_bytes"), + Help: proto.String("Free memory in bytes."), + Type: dto.MetricType_UNTYPED.Enum(), + Unit: proto.String("bytes"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("numa_node"), Value: proto.String("0")}, + }, + Untyped: &dto.Untyped{Value: proto.Float64(4294967296.0)}, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + { + Name: proto.String("rpc_duration_seconds"), + Help: proto.String("RPC latency summary in seconds."), + Type: dto.MetricType_SUMMARY.Enum(), + Unit: proto.String("seconds"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("service"), Value: proto.String("auth")}, + }, + Summary: &dto.Summary{ + SampleCount: proto.Uint64(100), + SampleSum: proto.Float64(25.5), + CreatedTimestamp: ×tamppb.Timestamp{Seconds: 1234567890}, + Quantile: []*dto.Quantile{ + {Quantile: proto.Float64(0.5), Value: proto.Float64(0.12)}, + {Quantile: proto.Float64(0.9), Value: proto.Float64(0.45)}, + {Quantile: proto.Float64(0.99), Value: proto.Float64(0.89)}, + }, + }, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + { + Name: proto.String("http_request_duration_seconds"), + Help: proto.String("HTTP request latency in seconds."), + Type: dto.MetricType_HISTOGRAM.Enum(), + Unit: proto.String("seconds"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("handler"), Value: proto.String("query")}, + {Name: proto.String("user_agent"), Value: proto.String("Mozilla/5.0 (with \\backslash, \"quotes\", and\nnewline)")}, + {Name: proto.String("region"), Value: proto.String("Björn-佖佥")}, + }, + Histogram: &dto.Histogram{ + SampleCount: proto.Uint64(2693), + SampleSum: proto.Float64(350.25), + CreatedTimestamp: ×tamppb.Timestamp{Seconds: 1234567890}, + Schema: proto.Int32(1), + ZeroThreshold: proto.Float64(0.001), + ZeroCount: proto.Uint64(2), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(2)}, + }, + PositiveDelta: []int64{1, 2}, + NegativeSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(1)}, + }, + NegativeDelta: []int64{1}, + Bucket: []*dto.Bucket{ + {UpperBound: proto.Float64(0.1), CumulativeCount: proto.Uint64(123)}, + { + UpperBound: proto.Float64(0.2), + CumulativeCount: proto.Uint64(412), + Exemplar: &dto.Exemplar{ + Label: []*dto.LabelPair{ + {Name: proto.String("trace_id"), Value: proto.String("abcdef123456")}, + }, + Value: proto.Float64(0.1152), + Timestamp: ×tamppb.Timestamp{Seconds: 1234567890}, + }, + }, + {UpperBound: proto.Float64(0.5), CumulativeCount: proto.Uint64(592)}, + {UpperBound: proto.Float64(math.Inf(+1)), CumulativeCount: proto.Uint64(2693)}, + }, + }, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + { + Name: proto.String("queue_latency_seconds"), + Help: proto.String("Gauge histogram of current queue wait time in seconds."), + Type: dto.MetricType_GAUGE_HISTOGRAM.Enum(), + Unit: proto.String("seconds"), + Metric: []*dto.Metric{ + { + Label: []*dto.LabelPair{ + {Name: proto.String("queue"), Value: proto.String("priority")}, + }, + Histogram: &dto.Histogram{ + SampleCount: proto.Uint64(500), + SampleSum: proto.Float64(750.5), + Schema: proto.Int32(1), + ZeroThreshold: proto.Float64(0.01), + ZeroCount: proto.Uint64(5), + PositiveSpan: []*dto.BucketSpan{ + {Offset: proto.Int32(0), Length: proto.Uint32(2)}, + }, + PositiveDelta: []int64{10, 15}, + Bucket: []*dto.Bucket{ + {UpperBound: proto.Float64(1.0), CumulativeCount: proto.Uint64(100)}, + {UpperBound: proto.Float64(2.0), CumulativeCount: proto.Uint64(350)}, + {UpperBound: proto.Float64(math.Inf(+1)), CumulativeCount: proto.Uint64(500)}, + }, + }, + TimestampMs: proto.Int64(1234567891000), + }, + }, + }, + } +} + +func BenchmarkConvertMetricFamily(b *testing.B) { + mfs := benchmarkMetricFamilies() + + for _, mf := range mfs { + b.Run("TEXT/"+mf.GetType().String(), func(b *testing.B) { + out := bytes.NewBuffer(make([]byte, 0, 1024)) + for b.Loop() { + _, err := MetricFamilyToText(out, mf) + if err != nil { + b.Fatal(err) + } + out.Reset() + } + }) + b.Run("OM1.0/"+mf.GetType().String(), func(b *testing.B) { + out := bytes.NewBuffer(make([]byte, 0, 1024)) + for b.Loop() { + _, err := MetricFamilyToOpenMetrics(out, mf) + if err != nil { + b.Fatal(err) + } + out.Reset() + } + }) + } +} diff --git a/expfmt/openmetrics_create_test.go b/expfmt/openmetrics_create_test.go index fa07aa8f..8419a698 100644 --- a/expfmt/openmetrics_create_test.go +++ b/expfmt/openmetrics_create_test.go @@ -21,7 +21,6 @@ import ( "time" dto "github.com/prometheus/client_model/go" - "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" @@ -785,104 +784,6 @@ name_count 2693 } } -func BenchmarkOpenMetricsCreate(b *testing.B) { - mf := &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("name_1"), - Value: proto.String("val with\nnew line"), - }, - { - Name: proto.String("name_2"), - Value: proto.String("val with \\backslash and \"quotes\""), - }, - { - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - { - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - { - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - { - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - { - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - { - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("name_1"), - Value: proto.String("Björn"), - }, - { - Name: proto.String("name_2"), - Value: proto.String("佖佥"), - }, - { - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(5699), - SampleSum: proto.Float64(49484343543.4343), - Bucket: []*dto.Bucket{ - { - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(120), - }, - { - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - { - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(596), - }, - { - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1535), - }, - }, - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - } - out := bytes.NewBuffer(make([]byte, 0, 1024)) - - for i := 0; i < b.N; i++ { - _, err := MetricFamilyToOpenMetrics(out, mf) - require.NoError(b, err) - out.Reset() - } -} - func TestOpenMetricsCreateError(t *testing.T) { scenarios := []struct { in *dto.MetricFamily diff --git a/expfmt/text_create_test.go b/expfmt/text_create_test.go index dc214966..82ac55d7 100644 --- a/expfmt/text_create_test.go +++ b/expfmt/text_create_test.go @@ -589,104 +589,6 @@ name_count 2693.123 } } -func BenchmarkCreate(b *testing.B) { - mf := &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("name_1"), - Value: proto.String("val with\nnew line"), - }, - { - Name: proto.String("name_2"), - Value: proto.String("val with \\backslash and \"quotes\""), - }, - { - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - { - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - { - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - { - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - { - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - { - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("name_1"), - Value: proto.String("Björn"), - }, - { - Name: proto.String("name_2"), - Value: proto.String("佖佥"), - }, - { - Name: proto.String("name_3"), - Value: proto.String("Just a quite long label value to test performance."), - }, - }, - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(5699), - SampleSum: proto.Float64(49484343543.4343), - Bucket: []*dto.Bucket{ - { - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(120), - }, - { - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - { - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(596), - }, - { - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1535), - }, - }, - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - } - out := bytes.NewBuffer(make([]byte, 0, 1024)) - - for i := 0; i < b.N; i++ { - _, err := MetricFamilyToText(out, mf) - require.NoError(b, err) - out.Reset() - } -} - func BenchmarkCreateBuildInfo(b *testing.B) { mf := &dto.MetricFamily{ Name: proto.String("benchmark_build_info"),