You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
attribute: split HashKVs benchmark by value type (#8268)
Fixes https://github.com/open-telemetry/opentelemetry-go/issues/8186 ``` $ go test -run=^$ -bench=BenchmarkHashKVs goos: linux goarch: amd64 pkg: go.opentelemetry.io/otel/attribute cpu: 13th Gen Intel(R) Core(TM) i7-13800H BenchmarkHashKVs/All-20 839494 1361 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/BoolTrue-20 35088729 32.42 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/BoolFalse-20 36449155 32.38 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/BoolSliceLen2-20 28046656 42.64 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/BoolSliceLen3-20 22122566 53.76 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/IntNegative-20 36561420 32.39 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/IntZero-20 37022479 32.37 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/IntSliceLen5-20 15606936 68.43 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/IntSliceLen1-20 30817665 36.52 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Int64One-20 36776829 32.38 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Int64-20 36773379 32.38 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Int64SliceLen4-20 19433444 61.40 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Int64SliceWithZero-20 18905888 61.50 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Float64-20 36545835 32.42 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Float64Large-20 36449190 32.39 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Float64SliceLen4-20 19807012 60.45 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/Float64SliceLarge-20 19765995 60.54 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/StringFoo-20 37433268 30.38 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/StringBar-20 39426048 30.27 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/StringSliceLen3-20 24419990 49.19 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/StringSliceLooksLikeIntSlice-20 33484728 35.28 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/ByteSliceFoo-20 39430366 30.28 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/ByteSliceLooksLikeIntSlice-20 33389854 31.70 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen0-20 36872172 29.91 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen1-20 26122180 46.75 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen2-20 16753401 71.05 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen3-20 12809509 90.30 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen4-20 10725681 112.8 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceLen5-20 9315831 128.6 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/SliceNested-20 5622141 212.6 ns/op 0 B/op 0 allocs/op BenchmarkHashKVs/EmptyValue-20 40395283 29.71 ns/op 0 B/op 0 allocs/op PASS ok go.opentelemetry.io/otel/attribute 36.381s ```
This commit is contained in:
+82
-46
@@ -15,50 +15,64 @@ import (
|
||||
"go.opentelemetry.io/otel/attribute/internal/xxhash"
|
||||
)
|
||||
|
||||
type keyVal struct {
|
||||
name string
|
||||
kv func(string) KeyValue
|
||||
}
|
||||
|
||||
// keyVals is all the KeyValue generators that are used for testing. This is
|
||||
// not []KeyValue so different keys can be used with the test Values.
|
||||
var keyVals = []func(string) KeyValue{
|
||||
func(k string) KeyValue { return Bool(k, true) },
|
||||
func(k string) KeyValue { return Bool(k, false) },
|
||||
func(k string) KeyValue { return BoolSlice(k, []bool{false, true}) },
|
||||
func(k string) KeyValue { return BoolSlice(k, []bool{true, true, false}) },
|
||||
func(k string) KeyValue { return Int(k, -1278) },
|
||||
func(k string) KeyValue { return Int(k, 0) }, // Should be different than false above.
|
||||
func(k string) KeyValue { return IntSlice(k, []int{3, 23, 21, -8, 0}) },
|
||||
func(k string) KeyValue { return IntSlice(k, []int{1}) },
|
||||
func(k string) KeyValue { return Int64(k, 1) }, // Should be different from true and []int{1}.
|
||||
func(k string) KeyValue { return Int64(k, 29369) },
|
||||
func(k string) KeyValue { return Int64Slice(k, []int64{3826, -38, -29, -1}) },
|
||||
func(k string) KeyValue { return Int64Slice(k, []int64{8, -328, 29, 0}) },
|
||||
func(k string) KeyValue { return Float64(k, -0.3812381) },
|
||||
func(k string) KeyValue { return Float64(k, 1e32) },
|
||||
func(k string) KeyValue { return Float64Slice(k, []float64{0.1, -3.8, -29., 0.3321}) },
|
||||
func(k string) KeyValue { return Float64Slice(k, []float64{-13e8, -32.8, 4., 1e28}) },
|
||||
func(k string) KeyValue { return String(k, "foo") },
|
||||
func(k string) KeyValue { return String(k, "bar") },
|
||||
func(k string) KeyValue { return StringSlice(k, []string{"foo", "bar", "baz"}) },
|
||||
func(k string) KeyValue { return StringSlice(k, []string{"[]i1"}) },
|
||||
func(k string) KeyValue { return ByteSlice(k, []byte("foo")) },
|
||||
func(k string) KeyValue { return ByteSlice(k, []byte("[]i1")) },
|
||||
func(k string) KeyValue { return Slice(k) },
|
||||
func(k string) KeyValue { return Slice(k, BoolValue(true)) },
|
||||
func(k string) KeyValue { return Slice(k, BoolValue(true), IntValue(42)) },
|
||||
func(k string) KeyValue {
|
||||
var keyVals = []keyVal{
|
||||
{name: "BoolTrue", kv: func(k string) KeyValue { return Bool(k, true) }},
|
||||
{name: "BoolFalse", kv: func(k string) KeyValue { return Bool(k, false) }},
|
||||
{name: "BoolSliceLen2", kv: func(k string) KeyValue { return BoolSlice(k, []bool{false, true}) }},
|
||||
{name: "BoolSliceLen3", kv: func(k string) KeyValue { return BoolSlice(k, []bool{true, true, false}) }},
|
||||
{name: "IntNegative", kv: func(k string) KeyValue { return Int(k, -1278) }},
|
||||
{name: "IntZero", kv: func(k string) KeyValue { return Int(k, 0) }}, // Should be different than false above.
|
||||
{name: "IntSliceLen5", kv: func(k string) KeyValue { return IntSlice(k, []int{3, 23, 21, -8, 0}) }},
|
||||
{name: "IntSliceLen1", kv: func(k string) KeyValue { return IntSlice(k, []int{1}) }},
|
||||
{
|
||||
name: "Int64One",
|
||||
kv: func(k string) KeyValue { return Int64(k, 1) },
|
||||
}, // Should be different from true and []int{1}.
|
||||
{name: "Int64", kv: func(k string) KeyValue { return Int64(k, 29369) }},
|
||||
{name: "Int64SliceLen4", kv: func(k string) KeyValue { return Int64Slice(k, []int64{3826, -38, -29, -1}) }},
|
||||
{name: "Int64SliceWithZero", kv: func(k string) KeyValue { return Int64Slice(k, []int64{8, -328, 29, 0}) }},
|
||||
{name: "Float64", kv: func(k string) KeyValue { return Float64(k, -0.3812381) }},
|
||||
{name: "Float64Large", kv: func(k string) KeyValue { return Float64(k, 1e32) }},
|
||||
{
|
||||
name: "Float64SliceLen4",
|
||||
kv: func(k string) KeyValue { return Float64Slice(k, []float64{0.1, -3.8, -29., 0.3321}) },
|
||||
},
|
||||
{
|
||||
name: "Float64SliceLarge",
|
||||
kv: func(k string) KeyValue { return Float64Slice(k, []float64{-13e8, -32.8, 4., 1e28}) },
|
||||
},
|
||||
{name: "StringFoo", kv: func(k string) KeyValue { return String(k, "foo") }},
|
||||
{name: "StringBar", kv: func(k string) KeyValue { return String(k, "bar") }},
|
||||
{name: "StringSliceLen3", kv: func(k string) KeyValue { return StringSlice(k, []string{"foo", "bar", "baz"}) }},
|
||||
{name: "StringSliceLooksLikeIntSlice", kv: func(k string) KeyValue { return StringSlice(k, []string{"[]i1"}) }},
|
||||
{name: "ByteSliceFoo", kv: func(k string) KeyValue { return ByteSlice(k, []byte("foo")) }},
|
||||
{name: "ByteSliceLooksLikeIntSlice", kv: func(k string) KeyValue { return ByteSlice(k, []byte("[]i1")) }},
|
||||
{name: "SliceLen0", kv: func(k string) KeyValue { return Slice(k) }},
|
||||
{name: "SliceLen1", kv: func(k string) KeyValue { return Slice(k, BoolValue(true)) }},
|
||||
{name: "SliceLen2", kv: func(k string) KeyValue { return Slice(k, BoolValue(true), IntValue(42)) }},
|
||||
{name: "SliceLen3", kv: func(k string) KeyValue {
|
||||
return Slice(k,
|
||||
StringValue("triad"),
|
||||
IntValue(3),
|
||||
BoolValue(false),
|
||||
)
|
||||
},
|
||||
func(k string) KeyValue {
|
||||
}},
|
||||
{name: "SliceLen4", kv: func(k string) KeyValue {
|
||||
return Slice(k,
|
||||
StringValue("quad"),
|
||||
IntValue(4),
|
||||
BoolValue(false),
|
||||
Float64Value(4.25),
|
||||
)
|
||||
},
|
||||
func(k string) KeyValue {
|
||||
}},
|
||||
{name: "SliceLen5", kv: func(k string) KeyValue {
|
||||
return Slice(k,
|
||||
StringValue("penta"),
|
||||
IntValue(5),
|
||||
@@ -66,8 +80,8 @@ var keyVals = []func(string) KeyValue{
|
||||
Float64Value(5.5),
|
||||
ByteSliceValue([]byte("five")),
|
||||
)
|
||||
},
|
||||
func(k string) KeyValue {
|
||||
}},
|
||||
{name: "SliceNested", kv: func(k string) KeyValue {
|
||||
return Slice(k,
|
||||
StringValue("nested"),
|
||||
SliceValue(Float64Value(math.Inf(1)), ByteSliceValue([]byte("bin"))),
|
||||
@@ -76,8 +90,8 @@ var keyVals = []func(string) KeyValue{
|
||||
StringValue("tail"),
|
||||
StringSliceValue([]string{"fallback"}),
|
||||
)
|
||||
},
|
||||
func(k string) KeyValue { return KeyValue{Key: Key(k)} }, // Empty value.
|
||||
}},
|
||||
{name: "EmptyValue", kv: func(k string) KeyValue { return KeyValue{Key: Key(k)} }},
|
||||
}
|
||||
|
||||
func TestHashKVs(t *testing.T) {
|
||||
@@ -112,21 +126,21 @@ func TestHashKVs(t *testing.T) {
|
||||
// Test all combinations of 1, 2, and 3 attributes with different keys and values.
|
||||
for _, key := range keys {
|
||||
for i := range keyVals {
|
||||
kvs := []KeyValue{keyVals[i](key)}
|
||||
kvs := []KeyValue{keyVals[i].kv(key)}
|
||||
assertUniqueHash(kvs)
|
||||
|
||||
for j := range keyVals {
|
||||
kvs := []KeyValue{
|
||||
keyVals[i](key),
|
||||
keyVals[j](key),
|
||||
keyVals[i].kv(key),
|
||||
keyVals[j].kv(key),
|
||||
}
|
||||
assertUniqueHash(kvs)
|
||||
|
||||
for k := range keyVals {
|
||||
kvs := []KeyValue{
|
||||
keyVals[i](key),
|
||||
keyVals[j](key),
|
||||
keyVals[k](key),
|
||||
keyVals[i].kv(key),
|
||||
keyVals[j].kv(key),
|
||||
keyVals[k].kv(key),
|
||||
}
|
||||
assertUniqueHash(kvs)
|
||||
}
|
||||
@@ -158,13 +172,35 @@ func slice(kvs []KeyValue) string {
|
||||
func BenchmarkHashKVs(b *testing.B) {
|
||||
attrs := make([]KeyValue, len(keyVals))
|
||||
for i := range keyVals {
|
||||
attrs[i] = keyVals[i]("k")
|
||||
attrs[i] = keyVals[i].kv("k")
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
hashKVs(attrs)
|
||||
benches := []struct {
|
||||
name string
|
||||
kvs []KeyValue
|
||||
}{
|
||||
{
|
||||
name: "All",
|
||||
kvs: attrs,
|
||||
},
|
||||
}
|
||||
for _, gen := range keyVals {
|
||||
benches = append(benches, struct {
|
||||
name string
|
||||
kvs []KeyValue
|
||||
}{
|
||||
name: gen.name,
|
||||
kvs: []KeyValue{gen.kv("k")},
|
||||
})
|
||||
}
|
||||
|
||||
for _, bench := range benches {
|
||||
b.Run(bench.name, func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
hashKVs(bench.kvs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user