Uh oh!
There was an error while loading. Please reload this page.
Move the cache for the marshaler methods to be stored on the RuntimeType instead of in a ConditionalWeakTable - #126621
Conversation
…ype instead of in a ConditionalWeakTable Should fixdotnet#126608
jkoritzinsky
commented
Apr 7, 2026
@MihuBot benchmark Interop.StructureToPtr |
Tagging subscribers to this area: @dotnet/area-system-reflection |
There was a problem hiding this comment.
Pull request overview
This PR moves the cache for Marshal.LayoutTypeMarshalerMethods from a ConditionalWeakTable<Type, …> to the per-RuntimeType generic cache infrastructure to address the reported interop performance regressions (issue #126608).
Changes:
- Adds
LayoutTypeMarshalerMethodsstorage toRuntimeType.CompositeCacheEntryso it can live in the existingRuntimeTypegeneric cache. - Refactors
LayoutTypeMarshalerMethodsto implementRuntimeType.IGenericCacheEntry<T>and retrieves it viaRuntimeType.GetOrCreateCacheEntry<T>(). - Switches from delegate creation (
CreateDelegate) to caching raw function pointers (MethodHandle.GetFunctionPointer) for the marshaler methods.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/coreclr/System.Private.CoreLib/src/System/RuntimeType.GenericCache.cs | Adds a new composite-cache field to hold the marshaler-methods cache on RuntimeType. |
src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs | Reworks LayoutTypeMarshalerMethods to use RuntimeType cache entries and cached function pointers instead of a ConditionalWeakTable. |
Uh oh!
There was an error while loading. Please reload this page.
MihuBot
commented
Apr 7, 2026
Interop.StructureToPtr
|
jkoritzinsky
commented
Apr 8, 2026
@MihuBot benchmark Interop.StructureToPtr |
MihuBot
commented
Apr 8, 2026
Interop.StructureToPtr
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Fixes#126608
Move the marshalling info to be cached on the type itself instead of in a ConditionalWeakTable.
Move some of the validation (in particular the "has layout" validation) to be done only at "create" time so we don't have to rerun it for every time someone calls the Marshal methods with the same (valid) type.
Use the blittable fallbacks on
StructureMarshaler<T>andLayoutClassMarshaler<T>instead of inlining the calls. The cost may go up slightly (delegate call to a method that callsSpanHelpers.Memmoveinstead of direct call toSpanHelpers.Memmove) but still much faster than the existing implementation that does the "is blittable" checks each time.