Summary
Generated IFieldCodec<T>.WriteField/ReadField implementations (emitted by SerializerGenerator) call _codecs.GetRequiredCodec<T>() per field during (de)serialization, rather than resolving each nested field's codec once and caching the reference.
Verified
src/Quark.CodeGenerator/SerializerGenerator.cs (around lines 652, 707) — generated write/read paths call the DI-backed ICodecProvider.GetRequiredCodec<T>() per field per call.
Why it matters
ICodecProvider.GetRequiredCodec<T>() goes through IServiceProvider.GetService<IFieldCodec<T>>() (src/Quark.Serialization/Providers/CodecProvider.cs:23-27) — a closed-generic DI resolution. MS.DI caches call sites internally so this is not a naive reflection lookup, but it's still a virtual/indirected resolution repeated per field per (de)serialize call, where a cached field reference would be a direct call.
Not yet confirmed as actually hot relative to the rest of the path — this needs profiling before prioritizing; filed for visibility, not as a confirmed bottleneck.
Suggested fix
Investigate whether SerializerGenerator can emit a per-type static/cached codec field (resolved once, e.g. lazily on first use or via a static constructor pattern) instead of a DI call per field per invocation. Needs a look at whether this fits cleanly with AOT/trim constraints and the existing codec registration lifecycle before committing to an approach.
References
src/Quark.CodeGenerator/SerializerGenerator.cs
src/Quark.Serialization/Providers/CodecProvider.cs
Summary
Generated
IFieldCodec<T>.WriteField/ReadFieldimplementations (emitted bySerializerGenerator) call_codecs.GetRequiredCodec<T>()per field during (de)serialization, rather than resolving each nested field's codec once and caching the reference.Verified
src/Quark.CodeGenerator/SerializerGenerator.cs(around lines 652, 707) — generated write/read paths call the DI-backedICodecProvider.GetRequiredCodec<T>()per field per call.Why it matters
ICodecProvider.GetRequiredCodec<T>()goes throughIServiceProvider.GetService<IFieldCodec<T>>()(src/Quark.Serialization/Providers/CodecProvider.cs:23-27) — a closed-generic DI resolution. MS.DI caches call sites internally so this is not a naive reflection lookup, but it's still a virtual/indirected resolution repeated per field per (de)serialize call, where a cached field reference would be a direct call.Not yet confirmed as actually hot relative to the rest of the path — this needs profiling before prioritizing; filed for visibility, not as a confirmed bottleneck.
Suggested fix
Investigate whether
SerializerGeneratorcan emit a per-type static/cached codec field (resolved once, e.g. lazily on first use or via a static constructor pattern) instead of a DI call per field per invocation. Needs a look at whether this fits cleanly with AOT/trim constraints and the existing codec registration lifecycle before committing to an approach.References
src/Quark.CodeGenerator/SerializerGenerator.cssrc/Quark.Serialization/Providers/CodecProvider.cs