When I force the C# AOT compiler with MethodImpl(MethodImplOptions.AggressiveInlining) to do a really long method:
At the very end, it stops inlining and starts calling every possible method (even simple getters):
Is there a way to prevent it from stopping the inlining? Is there some method inline limit that can be increased?
EDIT: I was hoping it wouldn't devolve into a "you shouldn't do that" response. Why I can't just ask the question without justifying? So, here is the justifying. My application is meant to be time performance oriented. I don't care if the compiled code is 10000x bigger. What matters to me is time performance and I can measure about 20% better time performance if this code is inlined.
EDIT2: I've made some reasearch and it seems that there exists configuration knobs for JIT https://github.com/steveharter/dotnet_coreclr/blob/master/Documentation/project-docs/clr-configuration-knobs.md Specifically there is a JITInlineSize knob. I've tried to set its value via ENV variable, but it doesn't help.
EDIT3: I've made a reproducible example. Please see https://github.com/dagid4/AotInlineLimitProof


Pretty sure that's not how that works.
The
MethodImplAttributeapplies to your method, andAggressiveInliningtells the JIT (and thus AOT) that it should inline your method if possible. If your method is too large - based apparently on the number of bytes it compiles to - then it will be called normally rather than inlined.Inlining can save a few cycles per invocation, and will happen automatically for trivial methods when optimization is enabled.
AggressiveInliningraises the threshold for inlining but doesn't guarantee that it will happen, or that the output code will be any better.Here's a direct quote from the docs:
And that's what's happening here.
You've told the compiler that it should do what it can to inline your "really long" (whatever that means) method, and it does its best to comply. Your method apparently calls a bunch of other methods that would normally be inlined, but doing so will make your method exceed the inlining limit. Since you've insisted that it be inlined, and inlining those other methods would prevent that, the compiler is balancing the books in favor of what you told it to do. If inlining those 'simple getter' calls would make your method too large to inline, they don't get inlined.
AggressiveInliningshould be used rarely if at all. If you look at the runtime source you'll find that the vast majority of cases where the standard libraries use it, it's a performance tweak for commonly-called methods that would be inlined under normal circumstances anyway.For example, AsyncTaskMethodBuilder has this:
That's a trivial getter that would normally be inlined, except in cases like yours where the JIT is already running low on space. It's important that accessing the
Taskbe as quick as possible though, thus the attribute. It should take priority over optimizations because it's a definite win to inline this.What it's not intended for is what you're trying to do: force the JIT to duplicate large chunks of your code inline.