防止JIT内联方法

时间:2011-03-02 14:53:06

标签: c# jit inlining

我有一种独特的情况。我一直在开发一个用于发送电子邮件的开源库。在这个库中,我需要一种可靠的方法来获取调用方法。我通过分析其中的StackTrace对象,使用StackFrame完成了此操作。这在调试模式项目中没有问题,其中优化已关闭。

当我切换到启用优化的发布模式时,会出现问题。堆栈跟踪如下所示:

> FindActionName at offset 66 in file:line:column <filename unknown>:0:0
> Email at offset 296 in file:line:column <filename unknown>:0:0
> CallingEmailFromRealControllerShouldFindMailersActionName at offset 184
     in file:line:column <filename unknown>:0:0
> _InvokeMethodFast at offset 0 in file:line:column <filename unknown>:0:0
> InvokeMethodFast at offset 152 in file:line:column <filename unknown>:0:0
...

这是从失败的单元测试中获得的。在这个跟踪的第3行中,我应该看到一个名为TestEmail的方法,它在别处定义,但我相信JITter正在内联它。我已经读过你可以通过使方法虚拟来防止内联,但这不起作用。有没有人知道一种可靠的方法来防止方法内联,所以你的方法会出现在堆栈跟踪中?

2 个答案:

答案 0 :(得分:34)

您可以使用MethodImplAttribute并指定MethodImplOptions.NoInlining

[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
    // do something
}

请注意,这仍然不能保证您可以获得源代码中看到的实际调用方法。您的方法不会被内联,但您的方法的调用者可以内联到自己的调用者等等。

答案 1 :(得分:5)

您可以使用标有System.Runtime.CompilerServices.CallerMemberNameAttribute的其他参数及其兄弟CallerFilePathCallerLineNumber。如果我理解正确的话,这应该会为您提供正确的方法名称,无论内容是什么都没有。你只会获得方法名称,我没有看到任何东西来获取类名/汇编等。

不言而喻,但只是为了确定......这样的事情应该在日志记录/诊断之外使用。

这样做的正确方法可能是:

我意识到这可能对斯科特没有任何帮助,但也许其他人可以从中受益。