From 97da6324cf980bd106841cf0272a52994a10c3a3 Mon Sep 17 00:00:00 2001 From: chankyin Date: Tue, 4 Feb 2025 10:29:47 +0800 Subject: [PATCH] test(util/labelindex): improve benchmarks to cover labels with two dimensions --- allinone/go.mod | 2 +- allinone/go.sum | 4 +- util/iter/iter.go | 11 +++ util/labelindex/selectors_bench_test.go | 115 +++++++++++++++--------- util/labelindex/sets_bench_test.go | 94 ++++++++++++------- webhook/go.mod | 2 +- webhook/go.sum | 4 +- 7 files changed, 152 insertions(+), 80 deletions(-) diff --git a/allinone/go.mod b/allinone/go.mod index 7883e0d..c9b7c7b 100644 --- a/allinone/go.mod +++ b/allinone/go.mod @@ -40,7 +40,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.57.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect diff --git a/allinone/go.sum b/allinone/go.sum index 474b5e0..b4cbd65 100644 --- a/allinone/go.sum +++ b/allinone/go.sum @@ -78,8 +78,8 @@ github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVho github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= -github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= +github.com/puzpuzpuz/xsync/v3 v3.4.1 h1:wWXLKXwzpsduC3kUSahiL45MWxkGb+AQG0dsri4iftA= +github.com/puzpuzpuz/xsync/v3 v3.4.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/util/iter/iter.go b/util/iter/iter.go index f5596a6..e9cafc8 100644 --- a/util/iter/iter.go +++ b/util/iter/iter.go @@ -252,6 +252,17 @@ func (iter Iter[T]) CollectSlice() []T { return output } +func (iter Iter[T]) Count() uint64 { + output := uint64(0) + + iter(func(_ T) Flow { + output++ + return Continue + }) + + return output +} + func FromMap[K comparable, V any](m map[K]V) Iter[Pair[K, V]] { return func(yield Yield[Pair[K, V]]) Flow { for k, v := range m { diff --git a/util/labelindex/selectors_bench_test.go b/util/labelindex/selectors_bench_test.go index 6b836b6..1ac93c6 100644 --- a/util/labelindex/selectors_bench_test.go +++ b/util/labelindex/selectors_bench_test.go @@ -16,71 +16,100 @@ package labelindex_test import ( "fmt" + "math/rand/v2" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kubewharf/podseidon/util/iter" "github.com/kubewharf/podseidon/util/labelindex" ) -const numSelectors = 10000 - func BenchmarkSelectorsInsert(b *testing.B) { index := labelindex.NewSelectors[string]() + rng := rand.New(rand.NewChaCha8([32]byte{})) + + items := make([]iter.Pair[string, metav1.LabelSelector], b.N/2*2) + appId := 0 + subAppId := 0 + + for itemId := range b.N / 2 { + if rng.IntN(2) == 0 { + appId++ + subAppId = 0 + } else { + subAppId++ + } - for appId := range b.N { - err := index.Track(fmt.Sprint(appId), metav1.LabelSelector{ - MatchLabels: map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(-appId), - "zzz": "zzz", - }, - }) - require.NoError(b, err) + items[itemId] = iter.NewPair(fmt.Sprintf("%d-%d", appId, subAppId), metav1.LabelSelector{MatchLabels: map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", + }}) + items[itemId+b.N/2] = iter.NewPair(fmt.Sprintf("%d-%d", appId, subAppId), metav1.LabelSelector{MatchLabels: map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(-appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", + }}) } - for appId := range b.N { - err := index.Track(fmt.Sprint(appId), metav1.LabelSelector{ - MatchLabels: map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(appId), - "zzz": "zzz", - }, - }) - require.NoError(b, err) + b.ResetTimer() + + for _, item := range items { + err := index.Track(item.Left, item.Right) + if err != nil { + b.Log(err) + b.FailNow() + } } } -func BenchmarkSelectorsQueryBroadExact(b *testing.B) { +func BenchmarkSelectorsQueryBroad(b *testing.B) { // Generate data index := labelindex.NewSelectors[string]() - for appId := range numSelectors { - err := index.Track(fmt.Sprint(appId), metav1.LabelSelector{ - MatchLabels: map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(appId), - "zzz": "zzz", - }, - }) - require.NoError(b, err) - } + rng := rand.New(rand.NewChaCha8([32]byte{})) - b.ResetTimer() + appId := 0 + subAppId := 0 + + for appId < b.N { + err := index.Track(fmt.Sprintf("%d-%d", appId, subAppId), metav1.LabelSelector{MatchLabels: map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", + }}) + if err != nil { + b.Log(err) + b.FailNow() + } - for appId := range b.N { - appIdString := fmt.Sprint(appId % numSelectors) + if rng.IntN(2) == 0 { + appId++ + subAppId = 0 + } else { + subAppId++ + } + } - resultIter, _ := index.Query(map[string]string{ - "aaa": "aaa", - "appId": appIdString, - "zzz": "zzz", - }) - result := resultIter.CollectSlice() + queries := iter.Map(iter.Range(0, b.N), func(appId int) map[string]string { + return map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(appId), + "subApp": "0", + "zzz": "zzz", + } + }).CollectSlice() + + b.ResetTimer() - assert.Len(b, result, 1) - assert.Equal(b, []string{appIdString}, result) + for _, query := range queries { + resultIter, _ := index.Query(query) + result := resultIter.Count() + assert.Equal(b, uint64(1), result) } } diff --git a/util/labelindex/sets_bench_test.go b/util/labelindex/sets_bench_test.go index e8af308..8079586 100644 --- a/util/labelindex/sets_bench_test.go +++ b/util/labelindex/sets_bench_test.go @@ -16,66 +16,98 @@ package labelindex_test import ( "fmt" + "math/rand/v2" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kubewharf/podseidon/util/iter" "github.com/kubewharf/podseidon/util/labelindex" ) -const numSets = 1000000 - func BenchmarkSetsInsert(b *testing.B) { index := labelindex.NewSets[string]() + rng := rand.New(rand.NewChaCha8([32]byte{})) + + items := make([]iter.Pair[string, map[string]string], b.N/2*2) + appId := 0 + subAppId := 0 - for appId := range b.N { - index.Track(fmt.Sprint(appId), map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(-appId), - "zzz": "zzz", + for itemId := range b.N / 2 { + if rng.IntN(2) == 0 { + appId++ + subAppId = 0 + } else { + subAppId++ + } + + items[itemId] = iter.NewPair(fmt.Sprintf("%d-%d", appId, subAppId), map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", + }) + items[itemId+b.N/2] = iter.NewPair(fmt.Sprintf("%d-%d", appId, subAppId), map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(-appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", }) } - for appId := range b.N { - index.Track(fmt.Sprint(appId), map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(appId), - "zzz": "zzz", - }) + b.ResetTimer() + + for _, item := range items { + index.Track(item.Left, item.Right) } } -func BenchmarkSetsQueryBroadExact(b *testing.B) { +func BenchmarkSetsQueryBroad(b *testing.B) { // Generate data index := labelindex.NewSets[string]() + rng := rand.New(rand.NewChaCha8([32]byte{})) - for appId := range numSets { - index.Track(fmt.Sprint(appId), map[string]string{ - "aaa": "aaa", - "appId": fmt.Sprint(appId), - "zzz": "zzz", - }) - } + appId := 0 + subAppId := 0 - b.ResetTimer() + for appId < b.N { + if rng.IntN(2) == 0 { + appId++ + subAppId = 0 + } else { + subAppId++ + } - for appId := range b.N { - appIdString := fmt.Sprint(appId % numSets) + index.Track(fmt.Sprintf("%d-%d", appId, subAppId), map[string]string{ + "aaa": "aaa", + "appId": fmt.Sprint(appId), + "subApp": fmt.Sprint(subAppId), + "zzz": "zzz", + }) + } - resultIter, err := index.Query(metav1.LabelSelector{ + queries := iter.Map(iter.Range(0, b.N), func(appId int) metav1.LabelSelector { + return metav1.LabelSelector{ MatchLabels: map[string]string{ "aaa": "aaa", - "appId": appIdString, + "appId": fmt.Sprint(appId), "zzz": "zzz", }, - }) + } + }).CollectSlice() + + b.ResetTimer() + + for _, query := range queries { + resultIter, err := index.Query(query) require.NoError(b, err) - result := resultIter.CollectSlice() + resultCount := resultIter.Count() - assert.Len(b, result, 1) - assert.Equal(b, []string{appIdString}, result) + if resultCount == 0 { + b.Fail() + b.Logf("query %v yields no results", query) + } } } diff --git a/webhook/go.mod b/webhook/go.mod index 44f6b48..924e6de 100644 --- a/webhook/go.mod +++ b/webhook/go.mod @@ -41,7 +41,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.57.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect diff --git a/webhook/go.sum b/webhook/go.sum index 474b5e0..b4cbd65 100644 --- a/webhook/go.sum +++ b/webhook/go.sum @@ -78,8 +78,8 @@ github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVho github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= -github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= +github.com/puzpuzpuz/xsync/v3 v3.4.1 h1:wWXLKXwzpsduC3kUSahiL45MWxkGb+AQG0dsri4iftA= +github.com/puzpuzpuz/xsync/v3 v3.4.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=