1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-09-16 09:26:25 +02:00

Do not cache reflect.ValueOf() in metrics Labels (#649)

* Benchmark label iterator

* Remove cachedValue, a minor optimization
This commit is contained in:
Joshua MacDonald
2020-04-20 20:29:46 -07:00
committed by GitHub
parent cf7c4e5328
commit e554562513
2 changed files with 40 additions and 9 deletions

View File

@@ -554,3 +554,38 @@ func BenchmarkBatchRecord_8Labels_4Instruments(b *testing.B) {
func BenchmarkBatchRecord_8Labels_8Instruments(b *testing.B) { func BenchmarkBatchRecord_8Labels_8Instruments(b *testing.B) {
benchmarkBatchRecord8Labels(b, 8) benchmarkBatchRecord8Labels(b, 8)
} }
// LabelIterator
func BenchmarkLabelIterator(b *testing.B) {
const labelCount = 1024
ctx := context.Background()
fix := newFixture(b)
var rec export.Record
fix.pcb = func(_ context.Context, processRec export.Record) error {
rec = processRec
return nil
}
keyValues := makeLabels(labelCount)
counter := fix.meter.NewInt64Counter("test.counter")
counter.Add(ctx, 1, keyValues...)
fix.sdk.Collect(ctx)
b.ResetTimer()
labels := rec.Labels()
iter := labels.Iter()
var val core.KeyValue
for i := 0; i < b.N; i++ {
if !iter.Next() {
iter = labels.Iter()
iter.Next()
}
val = iter.Label()
}
if false {
fmt.Println(val)
}
}

View File

@@ -92,10 +92,6 @@ type (
// the labels, copied into an array of the correct // the labels, copied into an array of the correct
// size for use as a map key. // size for use as a map key.
ordered orderedLabels ordered orderedLabels
// cachedValue contains a `reflect.Value` of the `ordered`
// member
cachedValue reflect.Value
} }
// mapkey uniquely describes a metric instrument in terms of // mapkey uniquely describes a metric instrument in terms of
@@ -174,8 +170,7 @@ var (
kvType = reflect.TypeOf(core.KeyValue{}) kvType = reflect.TypeOf(core.KeyValue{})
emptyLabels = labels{ emptyLabels = labels{
ordered: [0]core.KeyValue{}, ordered: [0]core.KeyValue{},
cachedValue: reflect.ValueOf([0]core.KeyValue{}),
} }
) )
@@ -393,13 +388,15 @@ func (m *SDK) makeLabels(kvs []core.KeyValue, sortSlice *sortedLabels) labels {
// NumLabels is a part of an implementation of the export.LabelStorage // NumLabels is a part of an implementation of the export.LabelStorage
// interface. // interface.
func (ls *labels) NumLabels() int { func (ls *labels) NumLabels() int {
return ls.cachedValue.Len() return reflect.ValueOf(ls.ordered).Len()
} }
// GetLabel is a part of an implementation of the export.LabelStorage // GetLabel is a part of an implementation of the export.LabelStorage
// interface. // interface.
func (ls *labels) GetLabel(idx int) core.KeyValue { func (ls *labels) GetLabel(idx int) core.KeyValue {
return ls.cachedValue.Index(idx).Interface().(core.KeyValue) // Note: The Go compiler successfully avoids an allocation for
// the interface{} conversion here:
return reflect.ValueOf(ls.ordered).Index(idx).Interface().(core.KeyValue)
} }
// Iter is a part of an implementation of the export.Labels interface. // Iter is a part of an implementation of the export.Labels interface.
@@ -459,7 +456,6 @@ func computeOrderedLabels(kvs []core.KeyValue) labels {
if ls.ordered == nil { if ls.ordered == nil {
ls.ordered = computeOrderedReflect(kvs) ls.ordered = computeOrderedReflect(kvs)
} }
ls.cachedValue = reflect.ValueOf(ls.ordered)
return ls return ls
} }