IsListType uses reflection and is expensive for hot paths

IsListType was causing ~100 allocations for a non list object. It is
used in a wide range of code, so perform a more targeted check.

The use of `%#v` in a hot return path for `fmt.Errorf()` was the main
victim.

Replace `%#v` with a typed error and create a cache of types that are
lists with a bounded size (probably not necessary, but safer).

```
BenchmarkGet-12          	  100000	    119635 ns/op	   20110 B/op	     206 allocs/op
BenchmarkWatchHTTP-12    	  100000	     65761 ns/op	    7296 B/op	     139 allocs/op

BenchmarkGet-12          	  100000	    109085 ns/op	   17831 B/op	     152 allocs/op
BenchmarkWatchHTTP-12    	  200000	     33966 ns/op	    1913 B/op	      30 allocs/op
```

Kubernetes-commit: 58fb665646aa4c1b63f1322a50e3af7a60e39886
This commit is contained in:
Clayton Coleman 2019-03-21 20:43:26 -04:00 committed by Kubernetes Publisher
parent dd5dd7ec7e
commit 9006e59e3b
1 changed files with 5 additions and 0 deletions

View File

@ -292,7 +292,12 @@ func checkName(obj runtime.Object, name, namespace string, namer ScopeNamer) err
}
// setObjectSelfLink sets the self link of an object as needed.
// TODO: remove the need for the namer LinkSetters by requiring objects implement either Object or List
// interfaces
func setObjectSelfLink(ctx context.Context, obj runtime.Object, req *http.Request, namer ScopeNamer) error {
// We only generate list links on objects that implement ListInterface - historically we duck typed this
// check via reflection, but as we move away from reflection we require that you not only carry Items but
// ListMeta into order to be identified as a list.
if !meta.IsListType(obj) {
requestInfo, ok := request.RequestInfoFrom(ctx)
if !ok {