Method inlining across native images of assemblies

2020-02-09 07:21发布

问题:

As explained in another question, Ngen is usually only allowed to inline methods across assemblies if the method has the TargetedPatchingOptOutAttribute set.

But is this also true for hard bound assemblies by using the DependencyAttribute with LoadHint.Always?

edit: Maybe the answer to my initial question is no, otherwise it would make no sense that the TargetedPatchingOptOutAttribute is used in mscorlib since this assembly is always hard bound (it has the DefaultDependencyAttribute set). So I'd like to rephrase my question: Is the TargetedPatchingOptOutAttribute the only way to get a method inlined across native images of assemblies?

回答1:

It seems like that other question led me to a completely wrong assumption. Methods in our own assemblies are inlined across native image boundries, even if they are neither hard bound nor have the TargetedPatchingOptOutAttribute set. This attribute only affects the .NET Framework assemblies.

A Microsoft blog post has a quite good section about the TargetedPatchingOptOutAttribute:

"Targeted Patching - Method lacks TargetedPatchingOptOutAttribute" - this relates to a new feature in CLR 4 where NGEN images are more version resilient. In a nutshell, we hope to be able to apply a patch or fix to mscorlib.dll and not have to recompile all the other native images on the machine that depend upon it. This should only apply to methods in the .NET framework class libraries because they are the only assemblies that can opt into this feature.

This means: Because .NET Framework assemblies now support targeted patching in .NET 4.0, methods from those assemblies usually can't be inlined. But methods that are marked with the TargetedPatchingOptOutAttribute are performance critical and therefore opt out of the targeted patching (which means if they are ever changed, all native images that use that method need to be recompiled). Since our own assemblis don't use targeted patching, there is no reason to prevent method inlining across native images.

To test this I created a small sample that shows the call stack of an exception thrown in a different assembly. Only my main method and the method that throwed the exception were in the call stack. Some other small methods placed in both the calling and called assembly (that do basically nothing more than calling the next method) were not in the call stack. This behavior didn't change after creating native images for the assemblies (yes, I checked that the native images were used).

TLDR version: Don't care about the TargetedPatchingOptOutAttribute, it should only be used in the .NET Framework assemblies. Method inlining of self developed assemblies works the same with Ngen and JIT.