Skip to content

Commit

Permalink
Reduce constrainLabels allocations (#1272)
Browse files Browse the repository at this point in the history
* Add bench

Signed-off-by: Bulat Khasanov <afti@yandex.ru>

* Reduce constrainLabels allocations

Signed-off-by: Bulat Khasanov <afti@yandex.ru>

---------

Signed-off-by: Bulat Khasanov <afti@yandex.ru>
  • Loading branch information
khasanovbi authored Jun 7, 2023
1 parent 8840afc commit a09a1d3
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
35 changes: 30 additions & 5 deletions prometheus/vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ import (
"github.com/prometheus/common/model"
)

var labelsPool = &sync.Pool{
New: func() interface{} {
return make(Labels)
},
}

func getLabelsFromPool() Labels {
return labelsPool.Get().(Labels)
}

func putLabelsToPool(labels Labels) {
for k := range labels {
delete(labels, k)
}

labelsPool.Put(labels)
}

// MetricVec is a Collector to bundle metrics of the same name that differ in
// their label values. MetricVec is not used directly but as a building block
// for implementations of vectors of a given metric type, like GaugeVec,
Expand Down Expand Up @@ -93,6 +111,8 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
// there for pros and cons of the two methods.
func (m *MetricVec) Delete(labels Labels) bool {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)

h, err := m.hashLabels(labels)
if err != nil {
return false
Expand All @@ -109,6 +129,8 @@ func (m *MetricVec) Delete(labels Labels) bool {
// To match curried labels with DeletePartialMatch, it must be called on the base vector.
func (m *MetricVec) DeletePartialMatch(labels Labels) int {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)

return m.metricMap.deleteByLabels(labels, m.curry)
}

Expand Down Expand Up @@ -229,6 +251,8 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
// for example GaugeVec.
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)

h, err := m.hashLabels(labels)
if err != nil {
return nil, err
Expand Down Expand Up @@ -647,15 +671,16 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
}

func constrainLabels(desc *Desc, labels Labels) Labels {
constrainedValues := make(Labels, len(labels))
constrainedLabels := getLabelsFromPool()
for l, v := range labels {
if i, ok := indexOf(l, desc.variableLabels.labelNames()); ok {
constrainedValues[l] = desc.variableLabels[i].Constrain(v)
continue
v = desc.variableLabels[i].Constrain(v)
}
constrainedValues[l] = v

constrainedLabels[l] = v
}
return constrainedValues

return constrainedLabels
}

func constrainLabelValues(desc *Desc, lvs []string, curry []curriedLabelValue) []string {
Expand Down
28 changes: 28 additions & 0 deletions prometheus/vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,13 @@ func testConstrainedCurryVec(t *testing.T, vec *CounterVec, constraint func(stri
})
}

func BenchmarkMetricVecWithBasic(b *testing.B) {
benchmarkMetricVecWith(b, Labels{
"l1": "onevalue",
"l2": "twovalue",
})
}

func BenchmarkMetricVecWithLabelValuesBasic(b *testing.B) {
benchmarkMetricVecWithLabelValues(b, map[string][]string{
"l1": {"onevalue"},
Expand Down Expand Up @@ -948,6 +955,27 @@ func benchmarkMetricVecWithLabelValuesCardinality(b *testing.B, nkeys, nvalues i
benchmarkMetricVecWithLabelValues(b, labels)
}

func benchmarkMetricVecWith(b *testing.B, labels map[string]string) {
var keys []string
for k := range labels {
keys = append(keys, k)
}

vec := NewGaugeVec(
GaugeOpts{
Name: "test",
Help: "helpless",
},
keys,
)

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
vec.With(labels)
}
}

func benchmarkMetricVecWithLabelValues(b *testing.B, labels map[string][]string) {
var keys []string
for k := range labels { // Map order dependent, who cares though.
Expand Down

0 comments on commit a09a1d3

Please sign in to comment.