mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Merge pull request #113326 from mborsz/bench3
Add benchmark for json.compact high cpu usage in watch
This commit is contained in:
commit
08644a12b3
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package endpoints
|
package endpoints
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -38,6 +39,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
@ -878,7 +880,7 @@ func BenchmarkWatchHTTP(b *testing.B) {
|
|||||||
item.Name = fmt.Sprintf("reasonable-name-%d", i)
|
item.Name = fmt.Sprintf("reasonable-name-%d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
runWatchHTTPBenchmark(b, items)
|
runWatchHTTPBenchmark(b, toObjectSlice(items), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkWatchHTTP_UTF8(b *testing.B) {
|
func BenchmarkWatchHTTP_UTF8(b *testing.B) {
|
||||||
@ -891,10 +893,18 @@ func BenchmarkWatchHTTP_UTF8(b *testing.B) {
|
|||||||
item.Name = fmt.Sprintf("翏Ŏ熡韐-%d", i)
|
item.Name = fmt.Sprintf("翏Ŏ熡韐-%d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
runWatchHTTPBenchmark(b, items)
|
runWatchHTTPBenchmark(b, toObjectSlice(items), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWatchHTTPBenchmark(b *testing.B, items []example.Pod) {
|
func toObjectSlice(in []example.Pod) []runtime.Object {
|
||||||
|
var res []runtime.Object
|
||||||
|
for _, pod := range in {
|
||||||
|
res = append(res, &pod)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func runWatchHTTPBenchmark(b *testing.B, items []runtime.Object, contentType string) {
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
simpleStorage := &SimpleRESTStorage{}
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(handler)
|
||||||
@ -909,6 +919,8 @@ func runWatchHTTPBenchmark(b *testing.B, items []example.Pod) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("unexpected error: %v", err)
|
b.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
request.Header.Add("Accept", contentType)
|
||||||
|
|
||||||
response, err := client.Do(request)
|
response, err := client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("unexpected error: %v", err)
|
b.Fatalf("unexpected error: %v", err)
|
||||||
@ -931,7 +943,7 @@ func runWatchHTTPBenchmark(b *testing.B, items []example.Pod) {
|
|||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
simpleStorage.fakeWatch.Action(actions[i%len(actions)], &items[i%len(items)])
|
simpleStorage.fakeWatch.Action(actions[i%len(actions)], items[i%len(items)])
|
||||||
}
|
}
|
||||||
simpleStorage.fakeWatch.Stop()
|
simpleStorage.fakeWatch.Stop()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -982,47 +994,63 @@ func BenchmarkWatchWebsocket(b *testing.B) {
|
|||||||
func BenchmarkWatchProtobuf(b *testing.B) {
|
func BenchmarkWatchProtobuf(b *testing.B) {
|
||||||
items := benchmarkItems(b)
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
simpleStorage := &SimpleRESTStorage{}
|
runWatchHTTPBenchmark(b, toObjectSlice(items), "application/vnd.kubernetes.protobuf")
|
||||||
handler := handle(map[string]rest.Storage{"simples": simpleStorage})
|
}
|
||||||
server := httptest.NewServer(handler)
|
|
||||||
defer server.Close()
|
type fakeCachingObject struct {
|
||||||
client := http.Client{}
|
obj runtime.Object
|
||||||
|
|
||||||
dest, _ := url.Parse(server.URL)
|
once sync.Once
|
||||||
dest.Path = "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/watch/simples"
|
raw []byte
|
||||||
dest.RawQuery = ""
|
err error
|
||||||
|
}
|
||||||
request, err := http.NewRequest("GET", dest.String(), nil)
|
|
||||||
if err != nil {
|
func (f *fakeCachingObject) CacheEncode(_ runtime.Identifier, encode func(runtime.Object, io.Writer) error, w io.Writer) error {
|
||||||
b.Fatalf("unexpected error: %v", err)
|
f.once.Do(func() {
|
||||||
}
|
buffer := bytes.NewBuffer(nil)
|
||||||
request.Header.Set("Accept", "application/vnd.kubernetes.protobuf")
|
f.err = encode(f.obj, buffer)
|
||||||
response, err := client.Do(request)
|
f.raw = buffer.Bytes()
|
||||||
if err != nil {
|
})
|
||||||
b.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
if f.err != nil {
|
||||||
if response.StatusCode != http.StatusOK {
|
return f.err
|
||||||
body, _ := ioutil.ReadAll(response.Body)
|
}
|
||||||
b.Fatalf("Unexpected response %#v\n%s", response, body)
|
|
||||||
}
|
_, err := w.Write(f.raw)
|
||||||
|
return err
|
||||||
wg := sync.WaitGroup{}
|
}
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
func (f *fakeCachingObject) GetObject() runtime.Object {
|
||||||
defer response.Body.Close()
|
return f.obj
|
||||||
if _, err := io.Copy(ioutil.Discard, response.Body); err != nil {
|
}
|
||||||
b.Error(err)
|
|
||||||
}
|
func (f *fakeCachingObject) GetObjectKind() schema.ObjectKind {
|
||||||
wg.Done()
|
return f.obj.GetObjectKind()
|
||||||
}()
|
}
|
||||||
|
|
||||||
actions := []watch.EventType{watch.Added, watch.Modified, watch.Deleted}
|
func (f *fakeCachingObject) DeepCopyObject() runtime.Object {
|
||||||
|
return &fakeCachingObject{obj: f.obj.DeepCopyObject()}
|
||||||
b.ResetTimer()
|
}
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
simpleStorage.fakeWatch.Action(actions[i%len(actions)], &items[i%len(items)])
|
var _ runtime.CacheableObject = &fakeCachingObject{}
|
||||||
}
|
var _ runtime.Object = &fakeCachingObject{}
|
||||||
simpleStorage.fakeWatch.Stop()
|
|
||||||
wg.Wait()
|
func wrapCachingObject(in []example.Pod) []runtime.Object {
|
||||||
b.StopTimer()
|
var res []runtime.Object
|
||||||
|
for _, pod := range in {
|
||||||
|
res = append(res, &fakeCachingObject{obj: &pod})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkWatchCachingObjectJSON(b *testing.B) {
|
||||||
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
|
runWatchHTTPBenchmark(b, wrapCachingObject(items), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkWatchCachingObjectProtobuf(b *testing.B) {
|
||||||
|
items := benchmarkItems(b)
|
||||||
|
|
||||||
|
runWatchHTTPBenchmark(b, wrapCachingObject(items), "application/vnd.kubernetes.protobuf")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user