From 226e7ca83dae33cbbe46ee600ca5b341a9ec852f Mon Sep 17 00:00:00 2001 From: warnar boekkooi Date: Sun, 1 Dec 2024 18:31:10 +0100 Subject: [PATCH 1/4] chore: add benchmark for AsFloat64Slice --- internal/attribute/attribute_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/attribute/attribute_test.go b/internal/attribute/attribute_test.go index 113b644c80e..e2c35d9706e 100644 --- a/internal/attribute/attribute_test.go +++ b/internal/attribute/attribute_test.go @@ -133,3 +133,13 @@ func BenchmarkStringSliceValue(b *testing.B) { sync = StringSliceValue(s) } } + +func BenchmarkAsFloat64Slice(b *testing.B) { + b.ReportAllocs() + var in interface{} = [2]float64{1, 2.3} + b.ResetTimer() + + for i := 0; i < b.N; i++ { + sync = AsFloat64Slice(in) + } +} From 2c2054faa2ca403fe23370e7bfd15cc369633397 Mon Sep 17 00:00:00 2001 From: warnar boekkooi Date: Sun, 1 Dec 2024 18:32:46 +0100 Subject: [PATCH 2/4] chore: refactor As*Slice to reduce allocations --- internal/attribute/attribute.go | 46 +++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/internal/attribute/attribute.go b/internal/attribute/attribute.go index 822d8479474..d8035a37bae 100644 --- a/internal/attribute/attribute.go +++ b/internal/attribute/attribute.go @@ -49,26 +49,24 @@ func AsBoolSlice(v interface{}) []bool { if rv.Type().Kind() != reflect.Array { return nil } - var zero bool - correctLen := rv.Len() - correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) - cpy := reflect.New(correctType) - _ = reflect.Copy(cpy.Elem(), rv) - return cpy.Elem().Slice(0, correctLen).Interface().([]bool) + cpy := make([]bool, rv.Len()) + if len(cpy) > 0 { + _ = reflect.Copy(reflect.ValueOf(cpy), rv) + } + return cpy } // AsInt64Slice converts an int64 array into a slice into with same elements as array. func AsInt64Slice(v interface{}) []int64 { rv := reflect.ValueOf(v) - if rv.Type().Kind() != reflect.Array { + if rv.Type().Kind() != reflect.Array || rv.Len() == 0 { return nil } - var zero int64 - correctLen := rv.Len() - correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) - cpy := reflect.New(correctType) - _ = reflect.Copy(cpy.Elem(), rv) - return cpy.Elem().Slice(0, correctLen).Interface().([]int64) + cpy := make([]int64, rv.Len()) + if len(cpy) > 0 { + _ = reflect.Copy(reflect.ValueOf(cpy), rv) + } + return cpy } // AsFloat64Slice converts a float64 array into a slice into with same elements as array. @@ -77,12 +75,11 @@ func AsFloat64Slice(v interface{}) []float64 { if rv.Type().Kind() != reflect.Array { return nil } - var zero float64 - correctLen := rv.Len() - correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) - cpy := reflect.New(correctType) - _ = reflect.Copy(cpy.Elem(), rv) - return cpy.Elem().Slice(0, correctLen).Interface().([]float64) + cpy := make([]float64, rv.Len()) + if len(cpy) > 0 { + _ = reflect.Copy(reflect.ValueOf(cpy), rv) + } + return cpy } // AsStringSlice converts a string array into a slice into with same elements as array. @@ -91,10 +88,9 @@ func AsStringSlice(v interface{}) []string { if rv.Type().Kind() != reflect.Array { return nil } - var zero string - correctLen := rv.Len() - correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) - cpy := reflect.New(correctType) - _ = reflect.Copy(cpy.Elem(), rv) - return cpy.Elem().Slice(0, correctLen).Interface().([]string) + cpy := make([]string, rv.Len()) + if len(cpy) > 0 { + _ = reflect.Copy(reflect.ValueOf(cpy), rv) + } + return cpy } From 7d1f5a3a8968d4cb8be45166b5d9464f36fdfddb Mon Sep 17 00:00:00 2001 From: warnar boekkooi Date: Sun, 1 Dec 2024 21:19:13 +0100 Subject: [PATCH 3/4] chore: add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a19036caee0..9d1073c1e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5929) - Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5929) - Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5929) +- Performance improvements for attribute value `AsStringSlice`, `AsFloat64Slice`, `AsInt64Slice`, `AsBoolSlice`. (#6011) ### Fixed From f44702f9550758645f0737af10f40057b0a0ceb3 Mon Sep 17 00:00:00 2001 From: Warnar Boekkooi Date: Mon, 2 Dec 2024 17:31:41 +0100 Subject: [PATCH 4/4] chore: remove duplicate len check --- internal/attribute/attribute.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/attribute/attribute.go b/internal/attribute/attribute.go index d8035a37bae..691d96c7554 100644 --- a/internal/attribute/attribute.go +++ b/internal/attribute/attribute.go @@ -59,7 +59,7 @@ func AsBoolSlice(v interface{}) []bool { // AsInt64Slice converts an int64 array into a slice into with same elements as array. func AsInt64Slice(v interface{}) []int64 { rv := reflect.ValueOf(v) - if rv.Type().Kind() != reflect.Array || rv.Len() == 0 { + if rv.Type().Kind() != reflect.Array { return nil } cpy := make([]int64, rv.Len())