k8s.io/kubernetes@v1.29.3/test/integration/apiserver/timestamp_transformer_test.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package apiserver 18 19 import ( 20 "context" 21 "encoding/json" 22 "math/rand" 23 "testing" 24 25 "github.com/stretchr/testify/require" 26 v1 "k8s.io/api/core/v1" 27 k8sfuzz "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" 28 "k8s.io/apimachinery/pkg/api/meta" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/apimachinery/pkg/runtime/serializer" 32 "k8s.io/apimachinery/pkg/util/managedfields" 33 "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager" 34 k8stest "k8s.io/kubernetes/pkg/api/testing" 35 ) 36 37 func convertToUnstructured(b *testing.B, obj runtime.Object) runtime.Object { 38 converter := managedfields.NewDeducedTypeConverter() 39 typed, err := converter.ObjectToTyped(obj) 40 require.NoError(b, err) 41 res, err := converter.TypedToObject(typed) 42 require.NoError(b, err) 43 return res 44 } 45 46 func doBench(b *testing.B, useUnstructured bool, shortCircuit bool) { 47 var ( 48 expectedLarge runtime.Object 49 actualLarge runtime.Object 50 expectedSmall runtime.Object 51 actualSmall runtime.Object 52 ) 53 54 scheme := runtime.NewScheme() 55 codecs := serializer.NewCodecFactory(scheme) 56 seed := rand.Int63() 57 fuzzer := k8sfuzz.FuzzerFor(k8stest.FuzzerFuncs, rand.NewSource(seed), codecs) 58 fuzzer.NilChance(0) 59 60 fuzzer.MaxDepth(1000).NilChance(0.2).NumElements(2, 15) 61 pod := &v1.Pod{} 62 fuzzer.Fuzz(pod) 63 64 fuzzer.NilChance(0.2).NumElements(10, 100).MaxDepth(10) 65 deployment := &v1.Endpoints{} 66 fuzzer.Fuzz(deployment) 67 68 bts, err := json.Marshal(deployment) 69 require.NoError(b, err) 70 b.Logf("Small (Deployment): %v bytes", len(bts)) 71 bts, err = json.Marshal(pod) 72 require.NoError(b, err) 73 b.Logf("Large (Pod): %v bytes", len(bts)) 74 75 expectedLarge = deployment 76 expectedSmall = pod 77 78 if useUnstructured { 79 expectedSmall = convertToUnstructured(b, expectedSmall) 80 expectedLarge = convertToUnstructured(b, expectedLarge) 81 } 82 83 actualLarge = expectedLarge.DeepCopyObject() 84 actualSmall = expectedSmall.DeepCopyObject() 85 86 if shortCircuit { 87 // Modify managed fields of the compared objects to induce a short circuit 88 now := metav1.Now() 89 extraEntry := &metav1.ManagedFieldsEntry{ 90 Manager: "sidecar_controller", 91 Operation: metav1.ManagedFieldsOperationApply, 92 APIVersion: "apps/v1", 93 Time: &now, 94 FieldsType: "FieldsV1", 95 FieldsV1: &metav1.FieldsV1{ 96 Raw: []byte(`{"f:metadata":{"f:labels":{"f:sidecar_version":{}}},"f:spec":{"f:template":{"f:spec":{"f:containers":{"k:{\"name\":\"sidecar\"}":{".":{},"f:image":{},"f:name":{}}}}}}}`), 97 }, 98 } 99 100 largeMeta, err := meta.Accessor(actualLarge) 101 require.NoError(b, err) 102 largeMeta.SetManagedFields(append(largeMeta.GetManagedFields(), *extraEntry)) 103 104 smallMeta, err := meta.Accessor(actualSmall) 105 require.NoError(b, err) 106 smallMeta.SetManagedFields(append(smallMeta.GetManagedFields(), *extraEntry)) 107 } 108 109 b.ResetTimer() 110 111 b.Run("Large", func(b2 *testing.B) { 112 for i := 0; i < b2.N; i++ { 113 if _, err := fieldmanager.IgnoreManagedFieldsTimestampsTransformer( 114 context.TODO(), 115 actualLarge, 116 expectedLarge, 117 ); err != nil { 118 b2.Fatal(err) 119 } 120 } 121 }) 122 123 b.Run("Small", func(b2 *testing.B) { 124 for i := 0; i < b2.N; i++ { 125 if _, err := fieldmanager.IgnoreManagedFieldsTimestampsTransformer( 126 context.TODO(), 127 actualSmall, 128 expectedSmall, 129 ); err != nil { 130 b2.Fatal(err) 131 } 132 } 133 }) 134 } 135 136 func BenchmarkIgnoreManagedFieldsTimestampTransformerStructuredShortCircuit(b *testing.B) { 137 doBench(b, false, true) 138 } 139 140 func BenchmarkIgnoreManagedFieldsTimestampTransformerStructuredWorstCase(b *testing.B) { 141 doBench(b, false, false) 142 } 143 144 func BenchmarkIgnoreManagedFieldsTimestampTransformerUnstructuredShortCircuit(b *testing.B) { 145 doBench(b, true, true) 146 } 147 148 func BenchmarkIgnoreManagedFieldsTimestampTransformerUnstructuredWorstCase(b *testing.B) { 149 doBench(b, true, false) 150 }