防止方法上的 JIT 内联

发布于 2024-10-19 19:40:13 字数 813 浏览 2 评论 0原文

我的情况比较特殊。我一直在开发一个用于发送电子邮件的开源库。在这个库中,我需要一种可靠的方法来获取调用方法。我通过分析 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 正在内联它。我读过,您可以通过将方法设为虚拟来防止内联,但这不起作用。有谁知道防止方法内联的可靠方法,以便您的方法将显示在堆栈跟踪中?

I've got sort of a unique situation. I've been working on an open source library for sending email. In this library, I need a reliable way to get the calling method. I've done this with a StackTrace by analyzing the StackFrame objects inside it. This works without issue in a debug-mode project where optimizations are turned off.

The problem occurs when I switch to release mode where optimizations are turned on. The stack trace looks like this:

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

This is taken from a failing unit test. In line 3 of this trace, I should see a method called TestEmail which is defined elsewhere, but I believe the JITter is inlining it. I've read that you can prevent inlining by making a method virtual, but this doesn't work. Does anyone know of a reliable method for preventing method inlining so your method will show up in a stack trace?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽清梦 2024-10-26 19:40:13

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

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

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

You could use MethodImplAttribute and specify MethodImplOptions.NoInlining.

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

Note that this still doesn't guarantee that you can get at the actual calling method as seen in the source code. Your method won't be inlined, but your method's caller could be inlined into its own caller, etc etc.

归途 2024-10-26 19:40:13

您可以使用标有 System.Runtime 的其他参数.CompilerServices.CallerMemberNameAttribute 及其同级 CallerFilePathCallerLineNumber。如果我理解正确的话,这应该会给你正确的方法名称,无论什么是内联的,什么不是。然而,您只会获得方法名称,我看不到任何获得类名称/程序集等的内容。

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

执行此操作的正确方法可能是:

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

You could use additional parameters marked with System.Runtime.CompilerServices.CallerMemberNameAttribute and it's siblings CallerFilePath and CallerLineNumber. If I understand it correctly this should get you the correct method name, no matter what's inlined an what's not. You will only get the method name however, I don't see anything to get the class name/assembly etc.

It should go without saying, but just to be sure... something like this should not be used outside of logging/diagnostics.

Proper ways to do this would probably be:

  • Pass the required information as a parameter
  • Temporarily store the required information in Thread.ExecutionContext while calling the function

I realize that this probably won't be of any help to Scott after all this time, but maybe someone else can benefit from it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文