问题描述
我写了一个记录器/ exceptionfactory模块,它采用System.Diagnostics.StackTrace,从调用方法和他们的声明类型获取属性。不过我注意到,如果我在释放模式下运行code的Visual Studio之外,我的一些较短的方法得到内联和堆栈跟踪丢失。现在我没有办法来测试是否一个方法将在运行时得到内联,但我不希望 [MethodImpl(MethodImplOptions.NoInlining)]
每一个重要方法。但是,如果从我的基类的方法将丢失的缘故吧,我误解了层和操作信息,并可能导致错误的日志或misparameterized例外。
I've written a logger/exceptionfactory module, which uses System.Diagnostics.StackTrace, to get attributes from calling methods and their declaring types. However I noticed, that if I run the code outside of Visual Studio in Release mode, some of my shorter methods get inlined and missing from the stack trace. Now I have no way to test whether a method will get inlined in runtime, but I do not want to [MethodImpl(MethodImplOptions.NoInlining)]
every important method. But if a method from my base classes will be missing because of it, I can misread the layer and operation information and that could lead to false log or misparameterized exceptions.
有一个经验法则是什么被内联何时何地?是虚拟的方法,静态方法,基类的方法治疗的有什么不同?难道我只是担心里面的内联汇编?内部空间?
Is there a rule of thumb what gets inlined where and when? Are virtual methods, static methods, base class methods treated any differently? Do I only have to worry about inlining inside assembly? Inside namespace?
推荐答案
是的,有一些规则,但他们所使用的JIT编译器启发而这些试探可以在片刻的通知来改变。
Yes, there are some rules but they are heuristics used by the JIT compiler and these heuristics can change at a moment's notice.
- 虚拟方法不能被内联。
- 在接口中的方法,在另一方面,也可以内联虽然我不是100%肯定这是否会崩溃的堆栈跟踪。
- 静态方法和非虚拟实例方法一定可以被内联。
- 内联可能跨越命名空间(当然)和组件(不是很明显),因为它发生在运行时,当JIT编译的方法调用。
- 在重方法不会被内联。这取决于重的定义,并且是JIT应用启发式的一部分。
一些启发式重,我所知道的:
Some of the heuristics for "heavy" that I'm aware of:
- 在该方法使用异常处理(即的try-catch或尝试-finally块)没有内联。
- 在大code(〜32 IL字节,但我可能会记住这个错误)不联方法。
- 与循环方法是不是内联(除非循环可以完全展开或消除)。
这篇关于堆栈跟踪记录在.NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!