Avoid intermediate allocations in MethodInfo/ConstructorInfo.Invoke#50814
Avoid intermediate allocations in MethodInfo/ConstructorInfo.Invoke#50814jkotas merged 11 commits intodotnet:mainfrom
Conversation
|
Note to reviewers: This will be easier to review with hide whitespace changes set. There's already significant unit and functional test coverage over all the reflection invocation code paths. I can't think offhand of any useful tests I could introduce alongside this change. But please feel free to offer suggestions and I can try to get them in. |
| private object? _arg6; | ||
| private object? _arg7; | ||
| #pragma warning restore CA1823, CS0169, IDE0051 | ||
| } |
There was a problem hiding this comment.
We now have a few of these floating around, e.g.
runtime/src/libraries/Common/src/Interop/Windows/SspiCli/SSPIWrapper.cs
Lines 218 to 224 in 79ae74f
and other places we'd wanted to but just didn't go to the lengths of creating these (there's also the additional zero'ing overhead that comes if you overestimate). At some point, we should think about doing something more general, whether it be enabling runtime support for stackalloc to work with reference types, or language support to create these types for stackallocs with const sizes, or a set of helper types we simply share either in Common or even publicly.
|
Can we add overloads to make these APIs support |
|
@davidfowl Feel free to bring that to API review. Though I suspect you'll be more interested in the other "fast reflection" work being considered, which significantly cuts the remaining overhead from these methods. See other reflection issues assigned to Steve or me for more info. |
|
Changes in latest update:
My benchmark machine is currently producing lots of noise at the moment (WU, perhaps?). But as a rough estimate it looks about inline with the previous iteration. |
Resolves #12832.
The managed reflection stack creates a defensive copy of the parameters
object[]array on calls toMethodInfo.InvokeandConstructorInfo.Invoketo prevent the parameter values changing between the initial type safety check and the real invocation of the target method. This PR special-cases "small" arrays (currently defined as <= 8 arguments) and creates a stack-based defensive copy instead of a heap-based defensive copy. This saves up to 88 bytes of heap allocations (on x64) perMethodInfo.InvokeorConstructorInfo.Invokecall.If 9 or more parameters are present, we fall back to the normal "allocate an array on the heap" code path.
I also took this opportunity to refactor some code that was on the
Invokehot paths, such as lazy initialization of theInvocationFlagsandSignatureproperties. These help offset some of the cost of setting up the struct-based argument holder.