aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

[AOT] Add middleware reflection fallback

Open JamesNK opened this issue 1 year ago • 2 comments

Addresses the warning part of https://github.com/dotnet/aspnetcore/issues/45528

Adds a reflection fallback to invoking middleware. The goal is to avoid native AOT warnings on publish.

There is also a small performance benefit to using reflection instead of an expression with AOT. Avoids allocating and running expression interpreter. The ideal solution to performance here is using source generation to invoke middleware. That is still to be done before https://github.com/dotnet/aspnetcore/issues/45528 is complete.

JamesNK avatar Jan 05 '23 06:01 JamesNK

@eerhardt After making these changes locally, updating the assembly in the SDK folder, and republishing, I still see expressions related warnings.

/_/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs(23): AOT analysis warning IL3050: System.Linq.Expressions.Interpreter.NewArrayInitInstruction.Run(InterpretedFrame): Using member 'System.Array.CreateInstance(Type,Int32)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The code for an array of the specified type might not be available. [C:\Users\james\source\repos\WebApplication25\WebApplication25\WebApplication25.csproj]
/_/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs(52): AOT analysis warning IL3050: System.Linq.Expressions.Interpreter.NewArrayInstruction.Run(InterpretedFrame): Using member 'System.Array.CreateInstance(Type,Int32)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The code for an array of the specified type might not be available. [C:\Users\james\source\repos\WebApplication25\WebApplication25\WebApplication25.csproj]
/_/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs(87): AOT analysis warning IL3050: System.Linq.Expressions.Interpreter.NewArrayBoundsInstruction.Run(InterpretedFrame): Using member 'System.Array.CreateInstance(Type,Int32[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The code for an array of the specifiedtype might not be available. [C:\Users\james\source\repos\WebApplication25\WebApplication25\WebApplication25.csproj]
/_/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs(28): AOT analysis warning IL3050: System.Dynamic.Utils.TypeUtils.GetNullableType(Type): Using member 'System.Type.MakeGenericType(Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [C:\Users\james\source\repos\WebApplication25\WebApplication25\WebApplication25.csproj]
/_/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs(1379): AOT analysis warning IL3050: System.Linq.Expressions.Expression.ApplyTypeArgs(MethodInfo,Type[]): Using member 'System.Reflection.MethodInfo.MakeGenericMethod(Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [C:\Users\james\source\repos\WebApplication25\WebApplication25\WebApplication25.csproj]

I mentioned on the original issue that it's odd the warnings are coming from System.Linq.Expressions files. Is the problem that System.Linq.Expressions is not correctly annotated?

Or am I not testing correctly? Or does the PR not correctly fix the cause of the warnings?

JamesNK avatar Jan 05 '23 06:01 JamesNK

I thought this was the issue.

davidfowl avatar Jan 05 '23 07:01 davidfowl

This doesn't fix the expressions AOT warnings, but IMO this change is still worthwhile. Invoking via raw reflection is better than interpreting compiled expressions. And this change is pretty modest, self-contained, and is on the critical path (called potentially multiple times per request). Source gen is the best solution, but this is a good improvement for existing libraries who call UseMiddleware<T>().

JamesNK avatar Jan 06 '23 13:01 JamesNK

Yes this is fine. The source gen will also be usable in libraries.

davidfowl avatar Jan 06 '23 13:01 davidfowl