Merge pull request #24727 from smarterclayton/fast_path_lookup
Automatic merge from submit-queue Avoid allocations and a reflect.Call in conversion reflect.Call is fairly expensive, performing 8 allocations and having to set up a call stack. Using a fairly straightforward to generate switch statement, we can bypass that early in conversion (as long as the function takes responsibility for invocation). We may also be able to avoid an allocation for the conversion scope, but not positive yet. ``` benchmark old ns/op new ns/op delta BenchmarkPodConversion-8 14713 12173 -17.26% benchmark old allocs new allocs delta BenchmarkPodConversion-8 80 72 -10.00% benchmark old bytes new bytes delta BenchmarkPodConversion-8 9133 8712 -4.61% ``` @wojtek-t related to #20309
This commit is contained in:
@@ -29,6 +29,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apimachinery"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
@@ -150,4 +151,89 @@ func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
|
||||
v1.AddToScheme(api.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// This is a "fast-path" that avoids reflection for common types. It focuses on the objects that are
|
||||
// converted the most in the cluster.
|
||||
// TODO: generate one of these for every external API group - this is to prove the impact
|
||||
api.Scheme.AddGenericConversionFunc(func(objA, objB interface{}, s conversion.Scope) (bool, error) {
|
||||
switch a := objA.(type) {
|
||||
case *v1.Pod:
|
||||
switch b := objB.(type) {
|
||||
case *api.Pod:
|
||||
return true, v1.Convert_v1_Pod_To_api_Pod(a, b, s)
|
||||
}
|
||||
case *api.Pod:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Pod:
|
||||
return true, v1.Convert_api_Pod_To_v1_Pod(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.Event:
|
||||
switch b := objB.(type) {
|
||||
case *api.Event:
|
||||
return true, v1.Convert_v1_Event_To_api_Event(a, b, s)
|
||||
}
|
||||
case *api.Event:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Event:
|
||||
return true, v1.Convert_api_Event_To_v1_Event(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.ReplicationController:
|
||||
switch b := objB.(type) {
|
||||
case *api.ReplicationController:
|
||||
return true, v1.Convert_v1_ReplicationController_To_api_ReplicationController(a, b, s)
|
||||
}
|
||||
case *api.ReplicationController:
|
||||
switch b := objB.(type) {
|
||||
case *v1.ReplicationController:
|
||||
return true, v1.Convert_api_ReplicationController_To_v1_ReplicationController(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.Node:
|
||||
switch b := objB.(type) {
|
||||
case *api.Node:
|
||||
return true, v1.Convert_v1_Node_To_api_Node(a, b, s)
|
||||
}
|
||||
case *api.Node:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Node:
|
||||
return true, v1.Convert_api_Node_To_v1_Node(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.Namespace:
|
||||
switch b := objB.(type) {
|
||||
case *api.Namespace:
|
||||
return true, v1.Convert_v1_Namespace_To_api_Namespace(a, b, s)
|
||||
}
|
||||
case *api.Namespace:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Namespace:
|
||||
return true, v1.Convert_api_Namespace_To_v1_Namespace(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.Service:
|
||||
switch b := objB.(type) {
|
||||
case *api.Service:
|
||||
return true, v1.Convert_v1_Service_To_api_Service(a, b, s)
|
||||
}
|
||||
case *api.Service:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Service:
|
||||
return true, v1.Convert_api_Service_To_v1_Service(a, b, s)
|
||||
}
|
||||
|
||||
case *v1.Endpoints:
|
||||
switch b := objB.(type) {
|
||||
case *api.Endpoints:
|
||||
return true, v1.Convert_v1_Endpoints_To_api_Endpoints(a, b, s)
|
||||
}
|
||||
case *api.Endpoints:
|
||||
switch b := objB.(type) {
|
||||
case *v1.Endpoints:
|
||||
return true, v1.Convert_api_Endpoints_To_v1_Endpoints(a, b, s)
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user