benchmark: measure label resolution in MetricVec
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
25db044749
commit
c4004ef5f6
|
@ -96,10 +96,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &CounterVec{
|
return &CounterVec{
|
||||||
MetricVec: MetricVec{
|
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
result := &counter{value: value{
|
result := &counter{value: value{
|
||||||
desc: desc,
|
desc: desc,
|
||||||
valType: CounterValue,
|
valType: CounterValue,
|
||||||
|
@ -107,8 +104,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||||
}}
|
}}
|
||||||
result.init(result) // Init self-collection.
|
result.init(result) // Init self-collection.
|
||||||
return result
|
return result
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,13 +72,9 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &GaugeVec{
|
return &GaugeVec{
|
||||||
MetricVec: MetricVec{
|
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newValue(desc, GaugeValue, 0, lvs...)
|
return newValue(desc, GaugeValue, 0, lvs...)
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -301,13 +301,9 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &HistogramVec{
|
return &HistogramVec{
|
||||||
MetricVec: MetricVec{
|
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newHistogram(desc, opts, lvs...)
|
return newHistogram(desc, opts, lvs...)
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -404,13 +404,9 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &SummaryVec{
|
return &SummaryVec{
|
||||||
MetricVec: MetricVec{
|
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newSummary(desc, opts, lvs...)
|
return newSummary(desc, opts, lvs...)
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,9 @@ func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec {
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &UntypedVec{
|
return &UntypedVec{
|
||||||
MetricVec: MetricVec{
|
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newValue(desc, UntypedValue, 0, lvs...)
|
return newValue(desc, UntypedValue, 0, lvs...)
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,16 @@ type MetricVec struct {
|
||||||
newMetric func(labelValues ...string) Metric
|
newMetric func(labelValues ...string) Metric
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newMetricVec returns an initialized MetricVec. The concrete value is
|
||||||
|
// returned for embedding into another struct.
|
||||||
|
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) MetricVec {
|
||||||
|
return MetricVec{
|
||||||
|
children: map[uint64]Metric{},
|
||||||
|
desc: desc,
|
||||||
|
newMetric: newMetric,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Describe implements Collector. The length of the returned slice
|
// Describe implements Collector. The length of the returned slice
|
||||||
// is always one.
|
// is always one.
|
||||||
func (m *MetricVec) Describe(ch chan<- *Desc) {
|
func (m *MetricVec) Describe(ch chan<- *Desc) {
|
||||||
|
|
|
@ -14,18 +14,12 @@
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
func TestDelete(t *testing.T) {
|
||||||
desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil)
|
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
|
||||||
vec := MetricVec{
|
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newValue(desc, UntypedValue, 0, lvs...)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want {
|
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want {
|
||||||
t.Errorf("got %v, want %v", got, want)
|
t.Errorf("got %v, want %v", got, want)
|
||||||
|
@ -57,14 +51,7 @@ func TestDelete(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteLabelValues(t *testing.T) {
|
func TestDeleteLabelValues(t *testing.T) {
|
||||||
desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil)
|
vec := newUntypedMetricVec("test", "helpless", []string{"l1", "l2"})
|
||||||
vec := MetricVec{
|
|
||||||
children: map[uint64]Metric{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: func(lvs ...string) Metric {
|
|
||||||
return newValue(desc, UntypedValue, 0, lvs...)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want {
|
if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want {
|
||||||
t.Errorf("got %v, want %v", got, want)
|
t.Errorf("got %v, want %v", got, want)
|
||||||
|
@ -86,3 +73,77 @@ func TestDeleteLabelValues(t *testing.T) {
|
||||||
t.Errorf("got %v, want %v", got, want)
|
t.Errorf("got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newUntypedMetricVec(name, help string, labels []string) *MetricVec {
|
||||||
|
desc := NewDesc("test", "helpless", labels, nil)
|
||||||
|
vec := newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
|
return newValue(desc, UntypedValue, 0, lvs...)
|
||||||
|
})
|
||||||
|
return &vec
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValuesBasic(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValues(B, map[string][]string{
|
||||||
|
"l1": []string{"onevalue"},
|
||||||
|
"l2": []string{"twovalue"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValues2Keys10ValueCardinality(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValuesCardinality(B, 2, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValues4Keys10ValueCardinality(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValuesCardinality(B, 4, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValues2Keys100ValueCardinality(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValuesCardinality(B, 2, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValues10Keys100ValueCardinality(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValuesCardinality(B, 10, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricVecWithLabelValues10Keys1000ValueCardinality(B *testing.B) {
|
||||||
|
benchmarkMetricVecWithLabelValuesCardinality(B, 10, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkMetricVecWithLabelValuesCardinality(B *testing.B, nkeys, nvalues int) {
|
||||||
|
labels := map[string][]string{}
|
||||||
|
|
||||||
|
for i := 0; i < nkeys; i++ {
|
||||||
|
var (
|
||||||
|
k = fmt.Sprintf("key-%v", i)
|
||||||
|
vs = make([]string, 0, nvalues)
|
||||||
|
)
|
||||||
|
for j := 0; j < nvalues; j++ {
|
||||||
|
vs = append(vs, fmt.Sprintf("value-%v", j))
|
||||||
|
}
|
||||||
|
labels[k] = vs
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarkMetricVecWithLabelValues(B, labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkMetricVecWithLabelValues(B *testing.B, labels map[string][]string) {
|
||||||
|
var keys []string
|
||||||
|
for k := range labels { // map order dependent, who cares though
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := make([]string, len(labels)) // value cache for permutations
|
||||||
|
vec := newUntypedMetricVec("test", "helpless", keys)
|
||||||
|
|
||||||
|
B.ReportAllocs()
|
||||||
|
B.ResetTimer()
|
||||||
|
for i := 0; i < B.N; i++ {
|
||||||
|
// varies input across provide map entries based on key size.
|
||||||
|
for j, k := range keys {
|
||||||
|
candidates := labels[k]
|
||||||
|
values[j] = candidates[i%len(candidates)]
|
||||||
|
}
|
||||||
|
|
||||||
|
vec.WithLabelValues(values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue