Can the ILEmit backend for dependency injection be made optional?
ThatRendle opened this issue · 4 comments
I know the new ILEmit engine for Dependency Injection is totally awesome and 25% faster, but it breaks AoT compilation with CoreRT because of the dependency on System.Reflection.Emit
: dotnet/corert#5720
I also know that AoT compilation of ASP.NET Core apps with CoreRT sounds very edge-casey and "why-would-you-do-that"-ish, and that for 99% of use cases, you probably wouldn't, but there are valid reasons to.
See, we're not just talking about ASP.NET Core here, we're talking about Kestrel and Hosting, and those are things you might want to use in very small console applications that you want to distribute as self-contained binary executables for use as services, for example.
Or you might want to compile a little reusable microservice to native code and drop it in a minimal Alpine-based Docker image.
I don't know what making this dependency "soft" would entail, whether it would be possible to drop it into a separate Microsoft.Extensions.DependencyInjection.ILEmit
package and then include that in Microsoft.AspNetCore.App
for convenience but allow people to skip it if they really want to? I don't know if controlling it via a Feature Flag would stop ILCompiler from choking on it.
I don't know anything, do I?
Discuss.
Currently, ILEmit is disabled by default in 2.1 but we are still planning to re-enable it in the future (2.2?).
Is there a runtime check to see if we are running on corert?
What would be the correct fallback? Expressions on reflection based resolution?
The most efficient pattern for CoreRT (and other AoT) is a combination of direct usage of reflection APIs and delegates from MethodInfo.CreateDelegate. Expressions work, but they're significantly less efficient.
If you know the signature of a method, generating delegates and calling them is extremely efficient. If you'd have to use MakeGenericType/MakeGenericMethod, it's only efficient if T is a reference type. If it's a struct, MethodInfo.Invoke is faster and potentially more reliable. The reason for the difference is that generics closed over reference types can use optimized shared generic code, but if they're closed over a struct that the compiler didn't predict, CoreRT doesn't currently have a fallback. .NET Native does have a fallback, but it's pretty slow.
We've talked about adding a runtime check API in the past, but I don't think it ever happened. It seems like a good 2.2 idea though. I've filed https://github.com/dotnet/corefx/issues/29258 to track it.
Waiting on dotnet/standard#832. Maybe we should expose the mode in the meantime.
This is tracked by dotnet/extensions#422