我可以检查C#编译器内联方法调用吗?

我正在写一个XNA游戏,我在那里进行逐像素碰撞检查。 通过移位int和按位ORing来检查这种情况的循环通常很难阅读和理解。

我想添加私有方法,如private bool IsTransparent(int pixelColorValue)以使循环更具可读性,但我不希望方法调用的开销,因为这是性能非常敏感的代码。

有没有办法强制编译器内联这个调用,或者我会这样做,我只希望编译器会进行这种优化?

如果没有办法强制执行此操作,是否有办法检查方法是否内联,而不是读取反汇编? 如果内联并且没有其他调用者存在,该方法是否会显示在reflection中?

编辑:我不能强迫它,所以我可以检测到它吗?

不,你不能。 更重要的是,决定内联的人不是VS编译器,它将代码转换为IL,而是JIT编译器,它接受IL并将其转换为机器代码。 这是因为只有JIT编译器对处理器体系结构有足够的了解才能确定将内联方法放在适当位置,因为它是指令流水线和缓存大小之间的权衡。

因此,即使查看.NET Reflector也无济于事。

“你可以检查System.Reflection.MethodBase.GetCurrentMethod()。Name。如果方法是内联的,它将返回调用者的名字。”

– Joel Coehoorn

有一种新方法可以鼓励在这里描述的.net 4.5中更具侵略性的内联: http : //blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive-inlining-in-the -clr-4-5-jit.aspx

基本上它只是一个标志,告诉编译器如果可能的话内联。 不幸的是,它在当前版本的XNA(Game Studio 4.0)中不可用,但是当XNA今年赶上VS 2012时应该可用。 如果您以某种方式在Mono上运行,它已经可用。

 [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LargeMethod(int i, int j) { if (i + 14 > j) { return i + j; } else if (j * 12 < i) { return 42 + i - j * 7; } else { return i % 14 - j; } } 

请注意,XBox的工作方式不同。

一个谷歌出现了这个:

“内联方法减轻了方法调用的开销.JIT形成内联,满足以下条件。

  • IL代码大小为16字节或更少。
  • 不使用分支命令(如果句子等)。
  • 不使用局部变量。
  • 尚未执行exception处理(尝试,捕获等)。
  • float不用作方法的参数或返回值(可能是由Xbox 360,未应用)。
  • 当一个方法中有两个或多个参数时,它用于声明的转弯。

但是,虚函数不会形成内联。“

http://xnafever.blogspot.com/2008/07/inline-method-by-xna-on-xbox360.html

我不知道他是否正确。 任何人?

不,你不能。

基本上,你不能在大多数现代C ++编译器中做到这一点。 inline只是编译器的一个提议。 它可以随意使用。

C#编译器不在IL级别进行任何特殊的内联。 JIT优化器就是这样做的。

为什么不使用不安全的代码(内联c作为其已知的)并使用c / c ++样式指针,这对GC是安全的(即不受集合影响)但具有其自身的安全隐患(不能用于互联网区域应用程序)但是对于你想要实现的那种东西,尤其是性能,以及arrays和按位运算更是如此,它是非常好的吗?

总而言之,您希望应用程序的一小部分性能? 使用不安全的代码并使用指针等对我来说似乎是最好的选择

编辑:有点启动? http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

检查此问题的唯一方法是获取或编写分析器,并挂钩到JIT事件,还必须确保在分析时默认情况下不会关闭内联。

您可以使用前面提到的GetCurrentMethod调用在运行时检测它。 但是,这似乎有点浪费[1]。 最容易做的就是ILDASM MSIL并检查那里。

请注意,这是专门用于内联调用的编译器 ,并在MSDN上的各种Reflection文档中介绍。

如果调用GetCallingAssembly方法的方法由编译器内联扩展(即,如果编译器将函数体插入到发出的Microsoft中间语言(MSIL)中,而不是发出函数调用),那么GetCallingAssembly返回的程序集method是包含内联代码的程序集。 这可能与包含原始方法的程序集不同。 要确保编译器不会内联调用GetCallingAssembly方法的方法,可以将MethodImplAttribute属性应用于MethodImplOptions.NoInlining。

但是,JITter也可以自由进行内联调用 – 但我认为反汇编程序将是validation该级别的内容和未执行内容的唯一方法。

编辑:只是为了清除这个线程中的一些混乱, csc.exe 内联MSIL调用 – 虽然JITter(可能)会更积极地进行调用 。

[1]而且,浪费 – 我的意思是(a)因为reflection查找而失去了内联的目的(更好的性能)。 并且(b),它可能会改变内联行为,因此无论如何它都不再内联。 并且,在您认为可以使用Assert或其他东西打开Debug版本之前 – 意识到它不会在Debug期间内联,但可能在Release中。

有没有办法强制编译器内联这个调用,或者我会这样做,我只希望编译器会进行这种优化?

如果内联函数更便宜,它会。 所以不要担心它,除非你的探查器说它实际上是一个问题。

欲获得更多信息

.NET 3.5 SP1中的JIT增强function