Skip to content

Commit e2b21c8

Browse files
authored
Merge pull request kubernetes#79946 from apelisse/add-apply-benchmarks
Add benchmarks for FieldManager handling
2 parents 57eef32 + 92cf376 commit e2b21c8

File tree

5 files changed

+382
-5
lines changed

5 files changed

+382
-5
lines changed

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ go_test(
4747
"//staging/src/k8s.io/api/core/v1:go_default_library",
4848
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
4949
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
50+
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
5051
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
5152
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
53+
"//vendor/sigs.k8s.io/yaml:go_default_library",
5254
],
5355
)

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go

Lines changed: 271 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ package fieldmanager_test
1818

1919
import (
2020
"errors"
21+
"fmt"
2122
"net/http"
2223
"testing"
2324

2425
corev1 "k8s.io/api/core/v1"
2526
apierrors "k8s.io/apimachinery/pkg/api/errors"
2627
"k8s.io/apimachinery/pkg/api/meta"
28+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2729
"k8s.io/apimachinery/pkg/runtime"
2830
"k8s.io/apimachinery/pkg/runtime/schema"
2931
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
32+
"sigs.k8s.io/yaml"
3033
)
3134

3235
type fakeObjectConvertor struct{}
@@ -48,7 +51,7 @@ type fakeObjectDefaulter struct{}
4851

4952
func (d *fakeObjectDefaulter) Default(in runtime.Object) {}
5053

51-
func NewTestFieldManager(t *testing.T) *fieldmanager.FieldManager {
54+
func NewTestFieldManager() *fieldmanager.FieldManager {
5255
gv := schema.GroupVersion{
5356
Group: "apps",
5457
Version: "v1",
@@ -63,13 +66,13 @@ func NewTestFieldManager(t *testing.T) *fieldmanager.FieldManager {
6366
}
6467

6568
func TestFieldManagerCreation(t *testing.T) {
66-
if NewTestFieldManager(t) == nil {
69+
if NewTestFieldManager() == nil {
6770
t.Fatal("failed to create FieldManager")
6871
}
6972
}
7073

7174
func TestApplyStripsFields(t *testing.T) {
72-
f := NewTestFieldManager(t)
75+
f := NewTestFieldManager()
7376

7477
obj := &corev1.Pod{}
7578

@@ -114,7 +117,7 @@ func TestApplyStripsFields(t *testing.T) {
114117
}
115118

116119
func TestVersionCheck(t *testing.T) {
117-
f := NewTestFieldManager(t)
120+
f := NewTestFieldManager()
118121

119122
obj := &corev1.Pod{}
120123

@@ -147,7 +150,7 @@ func TestVersionCheck(t *testing.T) {
147150
}
148151

149152
func TestApplyDoesNotStripLabels(t *testing.T) {
150-
f := NewTestFieldManager(t)
153+
f := NewTestFieldManager()
151154

152155
obj := &corev1.Pod{}
153156

@@ -173,3 +176,266 @@ func TestApplyDoesNotStripLabels(t *testing.T) {
173176
t.Fatalf("labels shouldn't get stripped on apply: %v", m)
174177
}
175178
}
179+
180+
func BenchmarkApplyNewObject(b *testing.B) {
181+
f := NewTestFieldManager()
182+
183+
obj := &corev1.Pod{}
184+
185+
b.ReportAllocs()
186+
b.ResetTimer()
187+
for n := 0; n < b.N; n++ {
188+
_, err := f.Apply(obj, []byte(`{
189+
"apiVersion": "apps/v1",
190+
"kind": "Pod",
191+
"metadata": {
192+
"name": "b",
193+
"namespace": "b",
194+
"creationTimestamp": "2016-05-19T09:59:00Z",
195+
},
196+
"map": {
197+
"fieldA": 1,
198+
"fieldB": 1,
199+
"fieldC": 1,
200+
"fieldD": 1,
201+
"fieldE": 1,
202+
"fieldF": 1,
203+
"fieldG": 1,
204+
"fieldH": 1,
205+
"fieldI": 1,
206+
"fieldJ": 1,
207+
"fieldK": 1,
208+
"fieldL": 1,
209+
"fieldM": 1,
210+
"fieldN": {
211+
"fieldN": {
212+
"fieldN": {
213+
"fieldN": {
214+
"fieldN": {
215+
"value": true
216+
},
217+
},
218+
},
219+
},
220+
},
221+
}
222+
}`), "fieldmanager_test", false)
223+
if err != nil {
224+
b.Fatal(err)
225+
}
226+
}
227+
}
228+
229+
func BenchmarkUpdateNewObject(b *testing.B) {
230+
f := NewTestFieldManager()
231+
232+
oldObj := &corev1.Pod{}
233+
y := `{
234+
"apiVersion": "apps/v1",
235+
"kind": "Deployment",
236+
"metadata": {
237+
"name": "b",
238+
"namespace": "b",
239+
"creationTimestamp": "2016-05-19T09:59:00Z",
240+
},
241+
"map": {
242+
"fieldA": 1,
243+
"fieldB": 1,
244+
"fieldC": 1,
245+
"fieldD": 1,
246+
"fieldE": 1,
247+
"fieldF": 1,
248+
"fieldG": 1,
249+
"fieldH": 1,
250+
"fieldI": 1,
251+
"fieldJ": 1,
252+
"fieldK": 1,
253+
"fieldL": 1,
254+
"fieldM": 1,
255+
"fieldN": {
256+
"fieldN": {
257+
"fieldN": {
258+
"fieldN": {
259+
"fieldN": {
260+
"value": true
261+
},
262+
},
263+
},
264+
},
265+
},
266+
},
267+
268+
}`
269+
newObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
270+
if err := yaml.Unmarshal([]byte(y), &newObj.Object); err != nil {
271+
b.Fatalf("Failed to parse yaml object: %v", err)
272+
}
273+
274+
b.ReportAllocs()
275+
b.ResetTimer()
276+
for n := 0; n < b.N; n++ {
277+
_, err := f.Update(oldObj, newObj, "fieldmanager_test")
278+
if err != nil {
279+
b.Fatal(err)
280+
}
281+
}
282+
}
283+
284+
func BenchmarkRepeatedUpdate(b *testing.B) {
285+
f := NewTestFieldManager()
286+
287+
var oldObj runtime.Object
288+
oldObj = &unstructured.Unstructured{Object: map[string]interface{}{}}
289+
y1 := `{
290+
"apiVersion": "apps/v1",
291+
"kind": "Deployment",
292+
"metadata": {
293+
"name": "b",
294+
"namespace": "b",
295+
"creationTimestamp": "2016-05-19T09:59:00Z",
296+
},
297+
"map": {
298+
"fieldA": 1,
299+
"fieldB": 1,
300+
"fieldC": 1,
301+
"fieldD": 1,
302+
"fieldE": 1,
303+
"fieldF": 1,
304+
"fieldG": 1,
305+
"fieldH": 1,
306+
"fieldI": 1,
307+
"fieldJ": 1,
308+
"fieldK": 1,
309+
"fieldL": 1,
310+
"fieldM": 1,
311+
"fieldN": {
312+
"fieldN": {
313+
"fieldN": {
314+
"fieldN": {
315+
"fieldN": {
316+
"value": true
317+
},
318+
},
319+
},
320+
},
321+
},
322+
},
323+
324+
}`
325+
obj1 := &unstructured.Unstructured{Object: map[string]interface{}{}}
326+
if err := yaml.Unmarshal([]byte(y1), &obj1.Object); err != nil {
327+
b.Fatalf("Failed to parse yaml object: %v", err)
328+
}
329+
y2 := `{
330+
"apiVersion": "apps/v1",
331+
"kind": "Deployment",
332+
"metadata": {
333+
"name": "b",
334+
"namespace": "b",
335+
"creationTimestamp": "2016-05-19T09:59:00Z",
336+
},
337+
"map": {
338+
"fieldA": 1,
339+
"fieldB": 1,
340+
"fieldC": 1,
341+
"fieldD": 1,
342+
"fieldE": 1,
343+
"fieldF": 1,
344+
"fieldG": 1,
345+
"fieldH": 1,
346+
"fieldI": 1,
347+
"fieldJ": 1,
348+
"fieldK": 1,
349+
"fieldL": 1,
350+
"fieldM": 1,
351+
"fieldN": {
352+
"fieldN": {
353+
"fieldN": {
354+
"fieldN": {
355+
"fieldN": {
356+
"value": false
357+
},
358+
},
359+
},
360+
},
361+
},
362+
},
363+
364+
}`
365+
obj2 := &unstructured.Unstructured{Object: map[string]interface{}{}}
366+
if err := yaml.Unmarshal([]byte(y2), &obj2.Object); err != nil {
367+
b.Fatalf("Failed to parse yaml object: %v", err)
368+
}
369+
y3 := `{
370+
"apiVersion": "apps/v1",
371+
"kind": "Deployment",
372+
"metadata": {
373+
"name": "b",
374+
"namespace": "b",
375+
"creationTimestamp": "2016-05-19T09:59:00Z",
376+
},
377+
"map": {
378+
"fieldA": 1,
379+
"fieldB": 1,
380+
"fieldC": 1,
381+
"fieldD": 1,
382+
"fieldE": 1,
383+
"fieldF": 1,
384+
"fieldG": 1,
385+
"fieldH": 1,
386+
"fieldI": 1,
387+
"fieldJ": 1,
388+
"fieldK": 1,
389+
"fieldL": 1,
390+
"fieldM": 1,
391+
"fieldN": {
392+
"fieldN": {
393+
"fieldN": {
394+
"fieldN": {
395+
"fieldN": {
396+
"value": true
397+
},
398+
},
399+
},
400+
},
401+
},
402+
"fieldO": 1,
403+
"fieldP": 1,
404+
"fieldQ": 1,
405+
"fieldR": 1,
406+
"fieldS": 1,
407+
},
408+
409+
}`
410+
obj3 := &unstructured.Unstructured{Object: map[string]interface{}{}}
411+
if err := yaml.Unmarshal([]byte(y3), &obj3.Object); err != nil {
412+
b.Fatalf("Failed to parse yaml object: %v", err)
413+
}
414+
415+
objs := []*unstructured.Unstructured{obj1, obj2, obj3}
416+
417+
var err error
418+
oldObj, err = f.Update(oldObj, objs[0], "fieldmanager_0")
419+
if err != nil {
420+
b.Fatal(err)
421+
}
422+
423+
oldObj, err = f.Update(oldObj, objs[1], "fieldmanager_1")
424+
if err != nil {
425+
b.Fatal(err)
426+
}
427+
428+
oldObj, err = f.Update(oldObj, objs[2], "fieldmanager_2")
429+
if err != nil {
430+
b.Fatal(err)
431+
}
432+
433+
b.ReportAllocs()
434+
b.ResetTimer()
435+
for n := 0; n < b.N; n++ {
436+
oldObj, err = f.Update(oldObj, objs[n%3], fmt.Sprintf("fieldmanager_%d", n%3))
437+
if err != nil {
438+
b.Fatal(err)
439+
}
440+
}
441+
}

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ go_test(
5353
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
5454
"//vendor/sigs.k8s.io/structured-merge-diff/fieldpath:go_default_library",
5555
"//vendor/sigs.k8s.io/structured-merge-diff/merge:go_default_library",
56+
"//vendor/sigs.k8s.io/structured-merge-diff/typed:go_default_library",
57+
"//vendor/sigs.k8s.io/structured-merge-diff/value:go_default_library",
5658
"//vendor/sigs.k8s.io/yaml:go_default_library",
5759
],
5860
)

0 commit comments

Comments
 (0)