Skip to content

Commit 6da4db6

Browse files
committed
Replace lookup map with a slice, improve variable names + comments, and add a benchmark for NewDesc
Signed-off-by: Kyle Eckhart <[email protected]>
1 parent d049c34 commit 6da4db6

File tree

4 files changed

+113
-49
lines changed

4 files changed

+113
-49
lines changed

prometheus/desc.go

+7-11
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,13 @@ type Desc struct {
5050
// variableLabels contains names of labels and normalization function for
5151
// which the metric maintains variable values.
5252
variableLabels *compiledLabels
53+
// variableLabelOrder maps variableLabels indexes to the position in the
54+
// pre-computed labelPairs slice. This allows fast MakeLabelPair function
55+
// that have to place ordered variable label values into pre-sorted labelPairs.
56+
variableLabelOrder []int
5357
// labelPairs contains the sorted DTO label pairs based on the constant labels
5458
// and variable labels
5559
labelPairs []*dto.LabelPair
56-
// variableLabelIndexesInLabelPairs holds all indexes variable labels in the
57-
// labelPairs with the expected index of the variableLabel. This makes it easy
58-
// to identify all variable labels in the labelPairs and where to get their value
59-
// from when given the variable label values
60-
variableLabelIndexesInLabelPairs map[int]int
6160
// id is a hash of the values of the ConstLabels and fqName. This
6261
// must be unique among all registered descriptors and can therefore be
6362
// used as an identifier of the descriptor.
@@ -179,18 +178,15 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const
179178
}
180179
sort.Sort(internal.LabelPairSorter(d.labelPairs))
181180

182-
// In order to facilitate mapping from the unsorted variable labels to
183-
// the sorted variable labels we generate a mapping from output labelPair
184-
// index -> variableLabel index for constructing the final label pairs later
185-
d.variableLabelIndexesInLabelPairs = make(map[int]int, len(d.variableLabels.names))
181+
d.variableLabelOrder = make([]int, len(d.variableLabels.names))
186182
for outputIndex, pair := range d.labelPairs {
187-
// Constant labels have values variable labels do not
183+
// Constant labels have values variable labels do not.
188184
if pair.Value != nil {
189185
continue
190186
}
191187
for sourceIndex, variableLabel := range d.variableLabels.names {
192188
if variableLabel == pair.GetName() {
193-
d.variableLabelIndexesInLabelPairs[outputIndex] = sourceIndex
189+
d.variableLabelOrder[sourceIndex] = outputIndex
194190
}
195191
}
196192
}

prometheus/desc_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package prometheus
1515

1616
import (
17+
"fmt"
1718
"testing"
1819
)
1920

@@ -61,3 +62,29 @@ func TestNewInvalidDesc_String(t *testing.T) {
6162
t.Errorf("String: unexpected output: %s", desc.String())
6263
}
6364
}
65+
66+
func BenchmarkNewDesc(b *testing.B) {
67+
for _, bm := range []struct {
68+
labelCount int
69+
descFunc func() *Desc
70+
}{
71+
{
72+
labelCount: 1,
73+
descFunc: new1LabelDescFunc,
74+
},
75+
{
76+
labelCount: 3,
77+
descFunc: new3LabelsDescFunc,
78+
},
79+
{
80+
labelCount: 10,
81+
descFunc: new10LabelsDescFunc,
82+
},
83+
} {
84+
b.Run(fmt.Sprintf("labels=%v", bm.labelCount), func(b *testing.B) {
85+
for i := 0; i < b.N; i++ {
86+
bm.descFunc()
87+
}
88+
})
89+
}
90+
}

prometheus/value.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -221,20 +221,22 @@ func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
221221
return desc.labelPairs
222222
}
223223
labelPairs := make([]*dto.LabelPair, 0, len(desc.labelPairs))
224-
for i, lp := range desc.labelPairs {
224+
for _, lp := range desc.labelPairs {
225225
var labelToAdd *dto.LabelPair
226-
// Variable labels have no value and need to be inserted with a new dto.LabelPair containing the labelValue
226+
// Variable labels have no value and need to be inserted with a new dto.LabelPair containing the labelValue.
227227
if lp.Value == nil {
228-
variableLabelIndex := desc.variableLabelIndexesInLabelPairs[i]
229228
labelToAdd = &dto.LabelPair{
230-
Name: lp.Name,
231-
Value: proto.String(labelValues[variableLabelIndex]),
229+
Name: lp.Name,
232230
}
233231
} else {
234232
labelToAdd = lp
235233
}
236234
labelPairs = append(labelPairs, labelToAdd)
237235
}
236+
for i, outputIndex := range desc.variableLabelOrder {
237+
labelPairs[outputIndex].Value = proto.String(labelValues[i])
238+
}
239+
238240
return labelPairs
239241
}
240242

prometheus/value_test.go

+72-33
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package prometheus
1515

1616
import (
17+
"fmt"
1718
"reflect"
1819
"testing"
1920
"time"
@@ -192,49 +193,87 @@ func TestMakeLabelPairs(t *testing.T) {
192193
}
193194
}
194195

195-
func Benchmark_MakeLabelPairs(b *testing.B) {
196-
benchFunc := func(desc *Desc, variableLabelValues []string) {
197-
MakeLabelPairs(desc, variableLabelValues)
198-
}
196+
var new1LabelDescFunc = func() *Desc {
197+
return NewDesc(
198+
"metric",
199+
"help",
200+
[]string{"var-label-1"},
201+
Labels{"const-label-1": "value"})
202+
}
203+
204+
var new3LabelsDescFunc = func() *Desc {
205+
return NewDesc(
206+
"metric",
207+
"help",
208+
[]string{"var-label-1", "var-label-3", "var-label-2"},
209+
Labels{"const-label-1": "value", "const-label-3": "value", "const-label-2": "value"})
210+
}
211+
212+
var new10LabelsDescFunc = func() *Desc {
213+
return NewDesc(
214+
"metric",
215+
"help",
216+
[]string{"var-label-5", "var-label-1", "var-label-3", "var-label-2", "var-label-10", "var-label-4", "var-label-7", "var-label-8", "var-label-9", "var-label-6"},
217+
Labels{"const-label-4": "value", "const-label-1": "value", "const-label-7": "value", "const-label-2": "value", "const-label-9": "value", "const-label-8": "value", "const-label-10": "value", "const-label-3": "value", "const-label-6": "value", "const-label-5": "value"})
218+
}
199219

200-
benchmarks := []struct {
201-
name string
202-
bench func(desc *Desc, variableLabelValues []string)
220+
func BenchmarkMakeLabelPairs(b *testing.B) {
221+
for _, bm := range []struct {
203222
desc *Desc
204-
variableLabelValues []string
223+
makeLabelPairValues []string
205224
}{
206225
{
207-
name: "1 label",
208-
desc: NewDesc(
209-
"metric",
210-
"help",
211-
[]string{"var-label-1"},
212-
Labels{"const-label-1": "value"}),
213-
variableLabelValues: []string{"value"},
226+
desc: new1LabelDescFunc(),
227+
makeLabelPairValues: []string{"value"},
214228
},
215229
{
216-
name: "3 labels",
217-
desc: NewDesc(
218-
"metric",
219-
"help",
220-
[]string{"var-label-1", "var-label-3", "var-label-2"},
221-
Labels{"const-label-1": "value", "const-label-3": "value", "const-label-2": "value"}),
222-
variableLabelValues: []string{"value", "value", "value"},
230+
desc: new3LabelsDescFunc(),
231+
makeLabelPairValues: []string{"value", "value", "value"},
223232
},
224233
{
225-
name: "10 labels",
226-
desc: NewDesc(
227-
"metric",
228-
"help",
229-
[]string{"var-label-5", "var-label-1", "var-label-3", "var-label-2", "var-label-10", "var-label-4", "var-label-7", "var-label-8", "var-label-9"},
230-
Labels{"const-label-4": "value", "const-label-1": "value", "const-label-7": "value", "const-label-2": "value", "const-label-9": "value", "const-label-8": "value", "const-label-10": "value", "const-label-3": "value", "const-label-6": "value", "const-label-5": "value"}),
231-
variableLabelValues: []string{"value", "value", "value", "value", "value", "value", "value", "value", "value", "value"},
234+
desc: new10LabelsDescFunc(),
235+
makeLabelPairValues: []string{"value", "value", "value", "value", "value", "value", "value", "value", "value", "value"},
232236
},
233-
}
234-
for _, bm := range benchmarks {
235-
b.Run(bm.name, func(b *testing.B) {
237+
} {
238+
b.Run(fmt.Sprintf("labels=%v", len(bm.makeLabelPairValues)), func(b *testing.B) {
236239
for i := 0; i < b.N; i++ {
237-
benchFunc(bm.desc, bm.variableLabelValues)
240+
MakeLabelPairs(bm.desc, bm.makeLabelPairValues)
241+
}
242+
})
243+
}
244+
}
245+
246+
func BenchmarkConstMetricFlow(b *testing.B) {
247+
for _, bm := range []struct {
248+
descFunc func() *Desc
249+
labelValues []string
250+
}{
251+
{
252+
descFunc: new1LabelDescFunc,
253+
labelValues: []string{"value"},
254+
},
255+
{
256+
descFunc: new3LabelsDescFunc,
257+
labelValues: []string{"value", "value", "value"},
258+
},
259+
{
260+
descFunc: new10LabelsDescFunc,
261+
labelValues: []string{"value", "value", "value", "value", "value", "value", "value", "value", "value", "value"},
262+
},
263+
} {
264+
b.Run(fmt.Sprintf("labels=%v", len(bm.labelValues)), func(b *testing.B) {
265+
for _, metricsToCreate := range []int{1, 2, 3, 5} {
266+
b.Run(fmt.Sprintf("metrics=%v", metricsToCreate), func(b *testing.B) {
267+
for i := 0; i < b.N; i++ {
268+
desc := bm.descFunc()
269+
for j := 0; j < metricsToCreate; j++ {
270+
_, err := NewConstMetric(desc, GaugeValue, 1.0, bm.labelValues...)
271+
if err != nil {
272+
b.Fatal(err)
273+
}
274+
}
275+
}
276+
})
238277
}
239278
})
240279
}

0 commit comments

Comments
 (0)