Skip to content

Commit 8df19b8

Browse files
committed
Optimize dpgSignature function in Prometheus receiver
This function is invoked very often, which leads to high CPU usage when collecting Prometheus metrics. Benchmark results on my machine show 3x less CPU and almost 4x less memory used. Since I'm also changing the format of returned values (dropping superfluous characters), it will reduce overall memory usage of the receiver, because they are used as map keys. Benchmark result before this change: Benchmark_dpgSignature-6 1284531 969.6 ns/op 120 B/op 7 allocs/op Benchmark result after this change: Benchmark_dpgSignature-6 3515179 313.9 ns/op 32 B/op 2 allocs/op
1 parent 9cf978e commit 8df19b8

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

receiver/prometheusreceiver/internal/metricsbuilder.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,27 @@ func isUsefulLabel(mType metricspb.MetricDescriptor_Type, labelKey string) bool
179179

180180
// dpgSignature is used to create a key for data complexValue belong to a same group of a metric family
181181
func dpgSignature(orderedKnownLabelKeys []string, ls labels.Labels) string {
182-
sign := make([]string, 0, len(orderedKnownLabelKeys))
182+
size := 0
183183
for _, k := range orderedKnownLabelKeys {
184184
v := ls.Get(k)
185185
if v == "" {
186186
continue
187187
}
188-
sign = append(sign, k+"="+v)
188+
// 2 enclosing quotes + 1 equality sign = 3 extra chars.
189+
// Note: if any character in the label value requires escaping,
190+
// we'll need more space than that, which will lead to some
191+
// extra allocation.
192+
size += 3 + len(k) + len(v)
189193
}
190-
return fmt.Sprintf("%#v", sign)
194+
sign := make([]byte, 0, size)
195+
for _, k := range orderedKnownLabelKeys {
196+
v := ls.Get(k)
197+
if v == "" {
198+
continue
199+
}
200+
sign = strconv.AppendQuote(sign, k+"="+v)
201+
}
202+
return string(sign)
191203
}
192204

193205
func normalizeMetricName(name string) string {

receiver/prometheusreceiver/internal/metricsbuilder_test.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package internal
1616

1717
import (
1818
"reflect"
19+
"runtime"
1920
"testing"
2021

2122
metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
@@ -1205,6 +1206,15 @@ func Test_isUsefulLabel(t *testing.T) {
12051206
}
12061207
}
12071208

1209+
func Benchmark_dpgSignature(b *testing.B) {
1210+
knownLabelKeys := []string{"a", "b"}
1211+
labels := labels.FromStrings("a", "va", "b", "vb", "x", "xa")
1212+
b.ReportAllocs()
1213+
for i := 0; i < b.N; i++ {
1214+
runtime.KeepAlive(dpgSignature(knownLabelKeys, labels))
1215+
}
1216+
}
1217+
12081218
func Test_dpgSignature(t *testing.T) {
12091219
knownLabelKeys := []string{"a", "b"}
12101220

@@ -1213,16 +1223,16 @@ func Test_dpgSignature(t *testing.T) {
12131223
ls labels.Labels
12141224
want string
12151225
}{
1216-
{"1st label", labels.FromStrings("a", "va"), `[]string{"a=va"}`},
1217-
{"2nd label", labels.FromStrings("b", "vb"), `[]string{"b=vb"}`},
1218-
{"two labels", labels.FromStrings("a", "va", "b", "vb"), `[]string{"a=va", "b=vb"}`},
1219-
{"extra label", labels.FromStrings("a", "va", "b", "vb", "x", "xa"), `[]string{"a=va", "b=vb"}`},
1220-
{"different order", labels.FromStrings("b", "vb", "a", "va"), `[]string{"a=va", "b=vb"}`},
1226+
{"1st label", labels.FromStrings("a", "va"), `"a=va"`},
1227+
{"2nd label", labels.FromStrings("b", "vb"), `"b=vb"`},
1228+
{"two labels", labels.FromStrings("a", "va", "b", "vb"), `"a=va""b=vb"`},
1229+
{"extra label", labels.FromStrings("a", "va", "b", "vb", "x", "xa"), `"a=va""b=vb"`},
1230+
{"different order", labels.FromStrings("b", "vb", "a", "va"), `"a=va""b=vb"`},
12211231
}
12221232
for _, tt := range tests {
12231233
t.Run(tt.name, func(t *testing.T) {
12241234
if got := dpgSignature(knownLabelKeys, tt.ls); got != tt.want {
1225-
t.Errorf("dpgSignature() = %v, want %v", got, tt.want)
1235+
t.Errorf("dpgSignature() = %q, want %q", got, tt.want)
12261236
}
12271237
})
12281238
}

0 commit comments

Comments
 (0)