Apply current parses the yaml object 3 times

This is super expensive and not needed at all since we don't have to
reparse the entire object. Remove all allocations but the first one.
This commit is contained in:
Antoine Pelisse 2019-09-25 12:38:38 -07:00
parent 08f46e425b
commit 31c644a1e7
4 changed files with 2 additions and 50 deletions

View File

@ -216,7 +216,7 @@ func (f *fieldManager) Apply(liveObj runtime.Object, patch []byte, fieldManager
}
internal.RemoveObjectManagedFields(liveObjVersioned)
patchObjTyped, err := f.typeConverter.YAMLToTyped(patch)
patchObjTyped, err := f.typeConverter.ObjectToTyped(patchObj)
if err != nil {
return nil, fmt.Errorf("failed to create typed patch object: %v", err)
}

View File

@ -27,7 +27,6 @@ go_library(
"//vendor/sigs.k8s.io/structured-merge-diff/merge:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/typed:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/value:go_default_library",
"//vendor/sigs.k8s.io/yaml:go_default_library",
],
)

View File

@ -25,14 +25,12 @@ import (
"k8s.io/kube-openapi/pkg/util/proto"
"sigs.k8s.io/structured-merge-diff/typed"
"sigs.k8s.io/structured-merge-diff/value"
"sigs.k8s.io/yaml"
)
// TypeConverter allows you to convert from runtime.Object to
// typed.TypedValue and the other way around.
type TypeConverter interface {
ObjectToTyped(runtime.Object) (*typed.TypedValue, error)
YAMLToTyped([]byte) (*typed.TypedValue, error)
TypedToObject(*typed.TypedValue) (runtime.Object, error)
}
@ -58,11 +56,6 @@ func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue
return typed.DeducedParseableType.FromUnstructured(u)
}
// YAMLToTyped parses a yaml object into a TypedValue with a "deduced type".
func (DeducedTypeConverter) YAMLToTyped(from []byte) (*typed.TypedValue, error) {
return typed.DeducedParseableType.FromYAML(typed.YAMLObject(from))
}
// TypedToObject transforms the typed value into a runtime.Object. That
// is not specific to deduced type.
func (DeducedTypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
@ -99,21 +92,6 @@ func (c *typeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, er
return t.FromUnstructured(u)
}
func (c *typeConverter) YAMLToTyped(from []byte) (*typed.TypedValue, error) {
unstructured := &unstructured.Unstructured{Object: map[string]interface{}{}}
if err := yaml.Unmarshal(from, &unstructured.Object); err != nil {
return nil, fmt.Errorf("error decoding YAML: %v", err)
}
gvk := unstructured.GetObjectKind().GroupVersionKind()
t := c.parser.Type(gvk)
if t == nil {
return nil, newNoCorrespondingTypeError(gvk)
}
return t.FromYAML(typed.YAMLObject(string(from)))
}
func (c *typeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
return valueToObject(value.AsValue())
}

View File

@ -124,9 +124,6 @@ spec:
t.Run(fmt.Sprintf("%v ObjectToTyped with TypeConverter", testCase.name), func(t *testing.T) {
testObjectToTyped(t, tc, testCase.yaml)
})
t.Run(fmt.Sprintf("%v YAMLToTyped with TypeConverter", testCase.name), func(t *testing.T) {
testYAMLToTyped(t, tc, testCase.yaml)
})
t.Run(fmt.Sprintf("%v ObjectToTyped with DeducedTypeConverter", testCase.name), func(t *testing.T) {
testObjectToTyped(t, dtc, testCase.yaml)
})
@ -155,31 +152,9 @@ Final object:
}
}
func testYAMLToTyped(t *testing.T, tc internal.TypeConverter, y string) {
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
if err := yaml.Unmarshal([]byte(y), &obj.Object); err != nil {
t.Fatalf("Failed to parse yaml object: %v", err)
}
yamlTyped, err := tc.YAMLToTyped([]byte(y))
if err != nil {
t.Fatalf("Failed to convert yaml to typed: %v", err)
}
newObj, err := tc.TypedToObject(yamlTyped)
if err != nil {
t.Fatalf("Failed to convert typed to object: %v", err)
}
if !reflect.DeepEqual(obj, newObj) {
t.Errorf(`YAML conversion resulted in different object failed:
Original object:
%#v
Final object:
%#v`, obj, newObj)
}
}
var result typed.TypedValue
func BenchmarkYAMLToTyped(b *testing.B) {
func BenchmarkObjectToTyped(b *testing.B) {
y := `
apiVersion: extensions/v1beta1
kind: Deployment