Unfortunately the proto id is now inconsistent with other "correct" objects,
but to change it will require a breaking serialization change. Worth considering.
RequestScope is a large struct and causes stack growth when we pass
it by value into multiple stack levels. Avoid the allocations for
this read only struct by passing a pointer.
A self link should only require one allocation, and we should skip
url.PathEscape() except when the path actually needs it.
Add a fuzz test to build random strings and verify them against
the optimized implementation. Add a new BenchmarkWatchHTTP_UTF8 that
covers when we have unicode names in the self link.
```
> before
BenchmarkGet-12 10000 118863 ns/op 17482 B/op 130 allocs/op
BenchmarkWatchHTTP-12 30000 38346 ns/op 1893 B/op 29 allocs/op
> after
BenchmarkGet-12 10000 116218 ns/op 17456 B/op 130 allocs/op
BenchmarkWatchHTTP-12 50000 35988 ns/op 1571 B/op 26 allocs/op
BenchmarkWatchHTTP_UTF8-12 50000 41467 ns/op 1928 B/op 28 allocs/op
```
Saves 3 allocations in the fast path and 1 in the slow path (the
slow path has to build the buffer and then call url.EscapedPath
which always allocates).
Time has a limited set of allowed characters and so can bypass part of
the expensive checking done for valid JSON characters.
```
BenchmarkGet-12 10000 111846 ns/op 17273 B/op 130 allocs/op
BenchmarkWatchHTTP-12 50000 37830 ns/op 1886 B/op 29 allocs/op
BenchmarkGet-12 20000 115917 ns/op 17344 B/op 130 allocs/op
BenchmarkWatchHTTP-12 50000 36741 ns/op 1775 B/op 24 allocs/op
```
Can improve CRD watch performance by 5-10% for small objects.
Clients are required to handle watch events of type ERROR, so instead
of eating the decoding error we should pass it on to the client. Use
NewGenericServerError with isUnexpectedResponse to indicate that we
didn't get the bytes from the server we were expecting. For watch, the
415 error code is roughly correct and we will return an error to the
client that makes debugging a failure in either server watch or client
machinery much easier.
We do not alter the behavior when it appears the response is an EOF
or other disconnection.
There was no reason to have two types and this avoids ~10% of allocations
on the GET code path.
```
BenchmarkGet-12 100000 109045 ns/op 17608 B/op 146 allocs/op
BenchmarkGet-12 100000 108850 ns/op 15942 B/op 132 allocs/op
```
ReplaceAllStrings always allocates, while scanning a relatively short
regex twice is slightly more CPU immediately but less later.
```
BenchmarkGet-12 100000 108824 ns/op 17818 B/op 152 allocs/op
BenchmarkGet-12 100000 108013 ns/op 17732 B/op 149 allocs/op
```
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
```
The kubelet was not asking for application/vnd.kubernetes.protobuf
on list and get calls. It looks like we lost that code when we
moved to cert rotation. Clean up the client initialization path
and make sure that all non-dynamic clients use protobuf by default.
The generated fake clientsets were using the API group "metrics" instead
of "metrics.k8s.io". This patch includes a test that fails without the
fix.
The `+groupName` annotation needed to be copied to the v1alpha1 and
v1beta1 packages to fix it.
As a result, tests using this fake clientset work as expected.
The Create, Delete, Get, Patch, Update and UpdateStatus
methods in the dynamic client all expect the name
parameter to be non-empty, but did not validate this
requirement, which could lead to a panic. Add explicit
checks to these methods.
Service account authorization checks are done frequently and were
observed to perform 7% of allocations on a system running e2e tests.
The allocation comes from when we walk the authorization rules to
find matching service accounts.
Optimize the check for service account names to avoid allocating.
UUIDv1 has several disadvantages:
- it encodes the MAC address of the host, which is a potential privacy issue
- it uses the clock of the host, which reveals time information
- the clock is very coarse, hence the complex code handling duplicates
UUIDv4 is simply a 122 bit random number encoded into the UUID format, which
has no problems with duplicates or locking.
Use the google/uuid library, as newer versions of pborman/uuid just wrap the
Google upstream.
Note that technically a random UUID might fail, but Go ensures that this
should not take place, as it will block if entropy is not available.
Signed-off-by: Justin Cormack <justin.cormack@docker.com>