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:
k8s-merge-robot
2016-05-06 07:10:18 -07:00
4 changed files with 131 additions and 0 deletions

View File

@@ -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
})
}