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?
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.