diff --git a/staging/src/k8s.io/client-go/tools/cache/thread_safe_store.go b/staging/src/k8s.io/client-go/tools/cache/thread_safe_store.go index 545fd3bb08a..c24a47b5616 100644 --- a/staging/src/k8s.io/client-go/tools/cache/thread_safe_store.go +++ b/staging/src/k8s.io/client-go/tools/cache/thread_safe_store.go @@ -18,6 +18,7 @@ package cache import ( "fmt" + "slices" "strconv" "sync" "time" @@ -205,8 +206,8 @@ func (i *storeIndex) updateSingleIndex(name string, oldObj interface{}, newObj i i.indices[name] = idx } - if len(indexValues) == 1 && len(oldIndexValues) == 1 && indexValues[0] == oldIndexValues[0] { - // We optimize for the most common case where indexFunc returns a single value which has not been changed + if slices.Equal(indexValues, oldIndexValues) { + // We optimize for the common case where indexFunc returns values which have not been changed return } diff --git a/staging/src/k8s.io/client-go/tools/cache/thread_safe_store_test.go b/staging/src/k8s.io/client-go/tools/cache/thread_safe_store_test.go index 77cb3ca71fd..a53b98f7d7f 100644 --- a/staging/src/k8s.io/client-go/tools/cache/thread_safe_store_test.go +++ b/staging/src/k8s.io/client-go/tools/cache/thread_safe_store_test.go @@ -377,30 +377,39 @@ func TestThreadSafeStoreTransactionRepeatedKeys(t *testing.T) { } func BenchmarkIndexer(b *testing.B) { - testIndexer := "testIndexer" - - indexers := Indexers{ - testIndexer: func(obj interface{}) (strings []string, e error) { - indexes := []string{obj.(string)} - return indexes, nil - }, - } - - indices := Indices{} - store := NewThreadSafeStore(indexers, indices).(*threadSafeMap) - // The following benchmark imitates what is happening in indexes // used in storage layer, where indexing is mostly static (e.g. // indexing objects by their (namespace, name)). // The 5000 number imitates indexing nodes in 5000-node cluster. - objectCount := 5000 - objects := make([]string, 0, 5000) - for i := 0; i < objectCount; i++ { - objects = append(objects, fmt.Sprintf("object-number-%d", i)) - } + for _, valuesPerObject := range []int{1, 10} { + b.Run(fmt.Sprintf("valuesPerObject=%d", valuesPerObject), func(b *testing.B) { + testIndexer := "testIndexer" + indexers := Indexers{ + testIndexer: func(obj interface{}) ([]string, error) { + return append([]string(nil), obj.([]string)...), nil + }, + } - b.ResetTimer() - for i := 0; i < b.N; i++ { - store.Update(objects[i%objectCount], objects[i%objectCount]) + store := NewThreadSafeStore(indexers, Indices{}).(*threadSafeMap) + objectCount := 5000 + keys := make([]string, objectCount) + objects := make([][]string, objectCount) + for i := range objectCount { + keys[i] = fmt.Sprintf("object-number-%d", i) + vals := make([]string, valuesPerObject) + for v := range valuesPerObject { + vals[v] = fmt.Sprintf("object-number-%d-val-%d", i, v) + } + objects[i] = vals + store.Add(keys[i], objects[i]) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + idx := i % objectCount + store.Update(keys[idx], objects[idx]) + } + }) } }