diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go index b0ea728fa71..ced184c91e5 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go @@ -20,6 +20,7 @@ import ( "encoding/json" "io" "reflect" + "sync" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -88,21 +89,34 @@ type codec struct { originalSchemeName string } +var identifiersMap sync.Map + +type codecIdentifier struct { + EncodeGV string `json:"encodeGV,omitempty"` + Encoder string `json:"encoder,omitempty"` + Name string `json:"name,omitempty"` +} + // identifier computes Identifier of Encoder based on codec parameters. func identifier(encodeGV runtime.GroupVersioner, encoder runtime.Encoder) runtime.Identifier { - result := map[string]string{ - "name": "versioning", + result := codecIdentifier{ + Name: "versioning", } + if encodeGV != nil { - result["encodeGV"] = encodeGV.Identifier() + result.EncodeGV = encodeGV.Identifier() } if encoder != nil { - result["encoder"] = string(encoder.Identifier()) + result.Encoder = string(encoder.Identifier()) + } + if id, ok := identifiersMap.Load(result); ok { + return id.(runtime.Identifier) } identifier, err := json.Marshal(result) if err != nil { klog.Fatalf("Failed marshaling identifier for codec: %v", err) } + identifiersMap.Store(result, runtime.Identifier(identifier)) return runtime.Identifier(identifier) } diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go index 0522a6827ef..14d598ff5b7 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_test.go @@ -381,3 +381,16 @@ func TestCacheableObject(t *testing.T) { runtimetesting.CacheableObjectTest(t, encoder) } + +func BenchmarkIdentifier(b *testing.B) { + encoder := &mockSerializer{} + gv := schema.GroupVersion{Group: "group", Version: "version"} + + for i := 0; i < b.N; i++ { + id := identifier(gv, encoder) + // Avoid optimizing by compiler. + if id[0] != '{' { + b.Errorf("unexpected identifier: %s", id) + } + } +} diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go b/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go index e1c948f62ae..2ef2cc6ece9 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go @@ -44,18 +44,18 @@ var AllowedFormats = []string{ } type backend struct { - out io.Writer - format string - groupVersion schema.GroupVersion + out io.Writer + format string + encoder runtime.Encoder } var _ audit.Backend = &backend{} func NewBackend(out io.Writer, format string, groupVersion schema.GroupVersion) audit.Backend { return &backend{ - out: out, - format: format, - groupVersion: groupVersion, + out: out, + format: format, + encoder: audit.Codecs.LegacyCodec(groupVersion), } } @@ -73,7 +73,7 @@ func (b *backend) logEvent(ev *auditinternal.Event) bool { case FormatLegacy: line = audit.EventString(ev) + "\n" case FormatJson: - bs, err := runtime.Encode(audit.Codecs.LegacyCodec(b.groupVersion), ev) + bs, err := runtime.Encode(b.encoder, ev) if err != nil { audit.HandlePluginError(PluginName, err, ev) return false