在.NET中记录登录的堆栈跟踪

5
我编写了一个记录器/异常工厂模块,它使用System.Diagnostics.StackTrace获取调用方法及其声明类型的属性。但是我发现,如果我在Release模式下在Visual Studio之外运行代码,则会省略某些较短的方法并从堆栈跟踪中丢失。现在我无法测试某个方法是否会在运行时内联,但我也不想对每个重要的方法使用[MethodImpl(MethodImplOptions.NoInlining)]。但如果由于这个原因我的基础类中的方法被省略了,那么我可能会误读层和操作信息,导致错误日志或参数化不当的异常。
有什么经验法则可以告诉我在何处和何时进行内联?虚方法、静态方法、基类方法是否有所不同?我只需要担心程序集内的内联吗?还是命名空间内的内联?

可能是当CLR可以将方法内联时?的重复问题。 - Hans Passant
2个回答

5

是的,有一些规则,但它们只是JIT编译器使用的启发式方法,这些启发式方法可能在瞬间发生变化。

  1. 虚方法不能被内联。
  2. 另一方面,接口方法可能会被内联,尽管我不确定是否会折叠堆栈跟踪。
  3. 静态方法和非虚实例方法肯定可以被内联。
  4. 内联可能会跨越命名空间(当然)和程序集(不太明显),因为它发生在运行时,当JIT编译方法调用时。
  5. "重"方法将不会被内联。这取决于“重”的定义,并且是JIT应用的启发式的一部分。

我知道一些“重”的启发式规则:

  • 使用异常处理(try-catch或try-finally块)的方法不会被内联。
  • 具有大量代码(~32个IL字节,但我可能记错了)的方法不会被内联。
  • 具有循环的方法不会被内联(除非循环可以完全展开或消除)。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接