Alerting: Improve performance of tupleLablesToLabels function (#88736)

* Alerting: Improve performance of tupleLablesToLabels function

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>

* use %s for string rather than %v

Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com>

---------

Signed-off-by: Dave Henderson <dave.henderson@grafana.com>
Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com>
This commit is contained in:
Dave Henderson 2024-06-05 09:19:09 -04:00 committed by GitHub
parent 3a6034b58e
commit df784917e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 122 additions and 4 deletions

View File

@ -100,12 +100,16 @@ func tupleLablesToLabels(tuples tupleLabels) (InstanceLabels, error) {
if tuples == nil {
return InstanceLabels{}, nil
}
labels := make(map[string]string)
labels := make(map[string]string, len(tuples))
for _, tuple := range tuples {
if key, ok := labels[tuple[0]]; ok {
return nil, fmt.Errorf("duplicate key '%v' in lables: %v", key, tuples)
key, value := tuple[0], tuple[1]
if _, ok := labels[key]; ok {
return nil, fmt.Errorf("duplicate key '%s' in labels: %v", key, tuples)
}
labels[tuple[0]] = tuple[1]
labels[key] = value
}
return labels, nil
}

View File

@ -0,0 +1,114 @@
package models
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestTupleLabelsToLabels(t *testing.T) {
t.Run("converts tupleLabels to InstanceLabels", func(t *testing.T) {
in := tupleLabels{
{"foo", "bar"},
{"baz", "qux"},
}
labels, err := tupleLablesToLabels(in)
require.NoError(t, err)
require.Equal(t, InstanceLabels{
"foo": "bar",
"baz": "qux",
}, labels)
})
t.Run("nil input gives empty output", func(t *testing.T) {
labels, err := tupleLablesToLabels(nil)
require.NoError(t, err)
require.Empty(t, labels)
})
t.Run("duplicate keys are not allowed", func(t *testing.T) {
in := tupleLabels{
{"foo", "bar"},
{"foo", "qux"},
}
_, err := tupleLablesToLabels(in)
require.Error(t, err)
})
}
func BenchmarkTupleLabelsToLabels(b *testing.B) {
b.Run("10 labels", func(b *testing.B) {
in := make(tupleLabels, 0, 10)
for i := 0; i < 10; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
in = append(in, tupleLabel{key, value})
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := tupleLablesToLabels(in)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("100 labels", func(b *testing.B) {
in := make(tupleLabels, 0, 100)
for i := 0; i < 100; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
in = append(in, tupleLabel{key, value})
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := tupleLablesToLabels(in)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("10_000 labels", func(b *testing.B) {
in := make(tupleLabels, 0, 10_000)
for i := 0; i < 10_000; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
in = append(in, tupleLabel{key, value})
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := tupleLablesToLabels(in)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("1_000_000 labels", func(b *testing.B) {
in := make(tupleLabels, 0, 1_000_000)
for i := 0; i < 1_000_000; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
in = append(in, tupleLabel{key, value})
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := tupleLablesToLabels(in)
if err != nil {
b.Fatal(err)
}
}
})
}