我已经观察到了应用程序中的许多“堆栈introspective”代码 不是 因其正确性而被绑架。这样的方法通常涉及到:

  • MethodBase.GetCurrentMethod
  • Assembly.GetCallingAssembly
  • Assembly.GetExecutingAssembly

现在,我发现围绕这些方法的信息非常令人困惑。我听说运行时不会嵌入一个调用GetCurrentMethod的方法,但我找不到任何文档来实现这种效果。我几次看过Stackoverflow上的帖子,例如 这个, ,指示CLR不会在线交叉组装呼叫,而是 GetCallingAssembly 文档 强烈指示其他方式。

也有很多疑问 [MethodImpl(MethodImplOptions.NoInlining)], ,但我不确定CLR是否认为这是“请求”或“命令”。

请注意,我在询问有关内部的信息 合格 从合同的角度来看 不是 关于当前抖动的实施何时由于实施困难而拒绝考虑方法,或者何时何时最终结束 选择 在评估权衡后,在符合条件的方法中内联方法。我读过了 这个这个, ,但它们似乎更专注于最后两个方面(正在提及方法论面。 义务).

什么时候CLR 允许 内联?

有帮助吗?

解决方案

这是一个抖动的实现细节,x86和x64抖动具有不同的规则。这是在抖动工作的团队成员的博客文章中随意记录的,但团队肯定保留更改规则的权利。看起来您已经找到了它们。

肯定会支持其他集会的方法,如果事实并非如此。当您查看为console.writeline()生成的机器代码时,您可以在工作中看到它,当您传递简单的字符串时,它通常会被内衬。要亲自查看此内容,您需要切换到发布构建并更改调试器选项。工具 +选项,调试,一般,打开“抑制对模块负载的JIT优化”。

否则没有充分的理由考虑methodimpotions。非误解,这几乎是为什么它首先存在的原因。实际上,它在.NET框架中有意使用许多称为内部辅助方法的小型公共方法。它使异常堆栈跟踪易于诊断。

其他提示

汉斯传递的回答尽管如此 这里 首先,截至2004年,有几个提示,并进一步了解更多最新信息。它们可能会发生变化,但是如果您想制作有资格的内部方法:

JIT不会嵌入式:

  • 用方法imploptions.noinlining标记的方法
  • 大于32个字节IL的方法
  • 虚拟方法
  • 将大价值类型作为参数的方法
  • 元帅课程的方法
  • 带有复杂流程图的方法
  • 符合其他更异国标准的方法

特别是 methodimploptions, ,这应该取消32个字节的限制(或如今的平台和平台上的任何东西)。

.NET 3.5添加了启发式方法,可以帮助它确定是否是否 内联或不在线, ,这可能是一件好事,尽管这使开发人员更难预测抖动的决定:

文章的报价:

  1. 如果内部的代码较小,则呼叫替换,它总是很好。请注意,我们谈论的是本地代码大小,而不是IL代码大小(可能完全不同)。

  2. 执行特定的呼叫站点越多,它就会从INLNING中受益。因此,循环中的代码值得被列入的代码不仅仅是不在循环中的代码。

  3. 如果内在揭示了重要的优化,那么内部的内部是更可取的。在具有价值类型参数的特定方法中,由于这样的优化,因此具有比正常情况更大的好处,因此存在偏见来嵌入这些方法是好的。

因此,X86 JIT编译器使用的启发式是给出的候选者。

  1. 如果该方法未内衬,则估计呼叫站点的大小。

  2. 估计呼叫站点的大小,如果它是内衬的(这是基于IL的估计值,我们使用一个简单的状态机(Markov模型),使用大量实际数据创建来形成此估算器逻辑)

  3. 计算乘数。默认情况下是1

  4. 如果代码处于循环中,则增加乘数(当前的启发式将其撞到5中)

  5. 如果乘数看起来会启动,则增加乘数。

  6. 如果Inlineize <= nonlinizizize *乘数进行内部。

尽管 汉斯的回答 是正确的,有一个遗漏,不一定是关于何时有资格进行内衬的,但是何时方法是 不是.

摘要和虚拟方法不符合在CLR中的内在条件.

重要的是要注意,因为它削弱了方法的条件 可能 被绑住。

有更多有关Methodbase.getCurrentMethod的信息 http://prdlxvm0001.codify.net/pipermail/ozdotnet/2011-march/009085.html

它严重地指出,Refcrawlmark并没有停止呼叫方法被内衬。但是,需要估算确实具有阻止呼叫者被绑定的侧面影响。

此外,汇编。getCallingAssembly和汇编。GetExeCutingAssembly方法没有此属性。

2003年在MSDN上发布了一篇文章 编写高性能托管应用程序 这涵盖了概述的几个标准:

  • 不超过32个字节的IL的方法不会被归类。
  • 虚拟函数没有嵌入。
  • 具有复杂流控制的方法不会被衬里。复杂的流量控制是除/then/否时的任何流控制;在这种情况下,切换或稍加切换。
  • 包含异常处理块的方法并未嵌入,尽管抛出异常的方法仍然是候选人的内衬。
  • 如果该方法的任何形式论点是构造,则该方法不会被归类。

Sacha Goldshtein在2012年的博客文章 在CLR中的积极内线 有很多相同的建议。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top