From 4d55c0687dbb6b6469bb17fd9e7e3b14ca6b4779 Mon Sep 17 00:00:00 2001 From: Ben Luddy Date: Mon, 11 Sep 2023 13:59:21 -0400 Subject: [PATCH] Reuse SupportedMediaTypes for CR content-type negotiation. In the course of calling NegotiateOutputMediaType, each CR endpoint handler invocation instantiates six JSON serializers. Each instantiation marshals the serializer options to JSON to construct the serializer identifier. Under heavy CR GET load, CPU profiling shows approximately 16% of the time spent in WriteObjectNegotiated was in SupportedMediaTypes, most of that within json.identifier(). --- .../pkg/apiserver/customresource_handler.go | 81 ++++++++++--------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index 2a6dcb80a7c..05b553ef864 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -833,6 +833,45 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd structuralSchemas: structuralSchemas, structuralSchemaGK: kind.GroupKind(), preserveUnknownFields: crd.Spec.PreserveUnknownFields, + supportedMediaTypes: []runtime.SerializerInfo{ + { + MediaType: "application/json", + MediaTypeType: "application", + MediaTypeSubType: "json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, creator, typer, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, creator, typer, true), + StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{ + Strict: true, + }), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, creator, typer, false), + Framer: json.Framer, + }, + }, + { + MediaType: "application/yaml", + MediaTypeType: "application", + MediaTypeSubType: "yaml", + EncodesAsText: true, + Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, creator, typer), + StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{ + Yaml: true, + Strict: true, + }), + }, + { + MediaType: "application/vnd.kubernetes.protobuf", + MediaTypeType: "application", + MediaTypeSubType: "vnd.kubernetes.protobuf", + Serializer: protobuf.NewSerializer(creator, typer), + StreamSerializer: &runtime.StreamSerializerInfo{ + Serializer: protobuf.NewRawSerializer(creator, typer), + Framer: protobuf.LengthDelimitedFramer, + }, + }, + }, } var standardSerializers []runtime.SerializerInfo for _, s := range negotiatedSerializer.SupportedMediaTypes() { @@ -1021,48 +1060,12 @@ type unstructuredNegotiatedSerializer struct { structuralSchemas map[string]*structuralschema.Structural // by version structuralSchemaGK schema.GroupKind preserveUnknownFields bool + + supportedMediaTypes []runtime.SerializerInfo } func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { - return []runtime.SerializerInfo{ - { - MediaType: "application/json", - MediaTypeType: "application", - MediaTypeSubType: "json", - EncodesAsText: true, - Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), - PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, true), - StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, s.creator, s.typer, json.SerializerOptions{ - Strict: true, - }), - StreamSerializer: &runtime.StreamSerializerInfo{ - EncodesAsText: true, - Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), - Framer: json.Framer, - }, - }, - { - MediaType: "application/yaml", - MediaTypeType: "application", - MediaTypeSubType: "yaml", - EncodesAsText: true, - Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, s.creator, s.typer), - StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, s.creator, s.typer, json.SerializerOptions{ - Yaml: true, - Strict: true, - }), - }, - { - MediaType: "application/vnd.kubernetes.protobuf", - MediaTypeType: "application", - MediaTypeSubType: "vnd.kubernetes.protobuf", - Serializer: protobuf.NewSerializer(s.creator, s.typer), - StreamSerializer: &runtime.StreamSerializerInfo{ - Serializer: protobuf.NewRawSerializer(s.creator, s.typer), - Framer: protobuf.LengthDelimitedFramer, - }, - }, - } + return s.supportedMediaTypes } func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {