Ani*_*Ani 37 .net clr jit inlining
我在应用程序中观察到了很多"堆栈内省"代码,这些代码通常隐含地依赖于它们的包含方法没有内联的正确性.这些方法通常涉及到:
MethodBase.GetCurrentMethod
Assembly.GetCallingAssembly
Assembly.GetExecutingAssembly
现在,我发现围绕这些方法的信息非常混乱.我听说运行时不会内联调用GetCurrentMethod的方法,但我找不到任何相关的文档.我曾多次在StackOverflow上看过帖子,比如这个帖子,表明CLR没有内联交叉汇编调用,但GetCallingAssembly
文档强烈指出不是这样.
还有备受诟病的人[MethodImpl(MethodImplOptions.NoInlining)]
,但我不确定CLR是否认为这是"请求"或"命令".
请注意,我要求从合同的角度来概述资格,而不是当前JITter的实施由于实施困难而拒绝考虑方法,或者JITter最终在评估交易后最终选择内联合格方法时权衡.我已经阅读了这个和这个,但他们似乎更关注最后两点(有传递提到的MethodImpOptions.NoInlining和"异国情调的IL指令",但这些似乎是作为启发而不是义务呈现).
什么时候CLR 允许内联?
Han*_*ant 23
这是一个抖动实现细节,x86和x64抖动具有微妙的不同规则.这是在团队成员的博客文章中随意记录的,这些团队成员处理抖动,但团队当然保留更改规则的权利.看起来你已经找到了它们.
当然,支持来自其他程序集的内联方法,如果不是这样的话,很多.NET类都会非常糟糕地工作.当您查看为Console.WriteLine()生成的机器代码时,您可以看到它正常工作,当您传递一个简单的字符串时,它经常被内联.要自己查看,需要切换到Release版本并更改调试器选项.工具+选项,调试,常规,取消勾选"在模块加载时抑制JIT优化".
否则没有充分的理由考虑MethodImpOptions.NoInlining malign,这就是它首先存在的原因.事实上它在.NET框架中故意用于许多调用内部帮助器方法的小型公共方法.它使异常堆栈跟踪更容易诊断.
尽管汉斯帕森特的回答是,在 2004年首先提出了几个提示,并进一步提供了一些更新的信息.它们可能会发生变化,但如果您想使方法符合内联条件,它们确实可以让您了解要查找的内容:
JIT不会内联:
- 用MethodImplOptions.NoInlining标记的方法
- 大于32字节的IL的方法
- 虚拟方法
- 将大值类型作为参数的方法
- MarshalByRef类的方法
- 具有复杂流程图的方法
- 满足其他更奇特标准的方法
特别是,有一个MethodImplOptions.AggressiveInlining,它应该提升32个字节的限制(或者现在和你的平台发生的任何事情).
.Net 3.5增加了启发式方法,帮助它确定是否内联,这可能是一件好事,尽管它使开发人员更难以预测抖动的决定:
文章的引用:
如果内联使代码变小,那么它所替换的调用就会很好.请注意,我们讨论的是NATIVE代码大小,而不是IL代码大小(可能完全不同).
特定呼叫站点的执行越多,它就越有利于inlning.因此,循环中的代码应该比不在循环中的代码更内联.
如果内联暴露了重要的优化,那么内联是更理想的.特别是具有值类型参数的方法由于这样的优化而受益于正常,因此具有内联这些方法的偏差是好的.
因此,给定内联候选者,X86 JIT编译器使用的启发式.
如果未内联方法,则估计调用站点的大小.
估计呼叫站点的大小(如果它是内联的(这是基于IL的估计,我们使用简单的状态机(马尔可夫模型),使用大量实际数据创建以形成此估计逻辑)
计算乘数.默认情况下为1
如果代码处于循环中,则增加乘数(当前启发式在循环中将其颠覆为5)
如果看起来结构优化将会起作用,请增加乘数.
如果InlineSize <= NonInlineSize*Multiplier执行内联.
归档时间: |
|
查看次数: |
4047 次 |
最近记录: |