记录类和方法名称的最高效方法是什么?

时间:2009-08-28 10:39:03

标签: c# .net reflection logging

我基本上想编写一个客户记录器/跟踪器,它还记录调用记录器/跟踪器的方法的类和方法名称。这应该很快,这样它不会影响应用程序的性能,强类型和清洁。有没有人有好主意?

以下是我所拥有的一些,但我担心由于反思而导致的表现:

  • StackTrace / StackFrame(开销太大了?)

  • MethodInfo.GetCurrentMethod()(还是太慢了?而且不是很干净)

  • 传递方法作为委托(C#可以隐式执行,我可以访问MethodInfo,但不是很干净)

我感谢任何人的评论。

更新

我喜欢StackFrame的无尘,所以我就StackFrame的性能提出了一个更具体的问题here,我得到了一些非常好的响应,包括性能测试。事实证明,MethodInfo.GetCurrentMethod()是最快的(在我的计算机上大约需要1微秒),new StackFrame(1)可以按需请求(在我的计算机上大约需要15-20微秒)。我将该方法作为委托选项抛出,因为当方法有多个参数时它太乱了。

结论:

我已经查看了所有选项,最好的是为PostSharp编写一个自定义插件,在编译时将方法名称作为字符串注入到MSIL中,同时应用[Trace]等自定义属性。在我看来,这是最快,最易维护的选择。这甚至可以实现更多的事情,比如传递参数名称和参数而不需要任何反射,并自动捕获和记录异常。这个my related question了解更多信息。

6 个答案:

答案 0 :(得分:4)

最快的方法是在编译时这样做,这是事实,但在.NET中最方便的方法是使用CallerMemberNameCallerFilePath和其他编译器服务属性在.NET 4.5中生成:

public void TraceMethodCall([CallerMemberName]string methodName)
{
}

答案 1 :(得分:3)

简单地说,最快的方法是在编译时静态地完成它:

public void DoSomething()
{
    TraceCall("DoSomething");
} 

public void TraceCall(string methodName)
{
    if (!tracingEnabled) { return; }
    // Log the call
}

那么问题与你之前的问题基本相同;在可维护和准确的情况下,最好的方法是什么?我们之前讨论的运行时选项会受到相对严重的性能影响,但权衡的是它们可以轻松实现。

正如前面提到的那样,这开始倾向于面向方面的编程; PostSharp就是这样一个库,可以通过简单的维护帮助找到静态编译性能的平衡。

答案 2 :(得分:2)

当你已经进入方法时(或者如果你正在拦截方法),我认为你不能比MethodInfo.GetCurrentMethod做得更好 - 这不是太快 - 如果你想留下类型 - 安全

由于您希望对日志记录执行此操作,您是否考虑过在异步操作中执行此操作以便不会减慢主线程的速度?

根据应用程序上已有的负载,它可能会有所帮助,也可能没有帮助。

答案 3 :(得分:0)

执行此操作的最佳方法是在编译时:C ++传统上使用宏中的____FILE __和____LINE____预处理程序符号来执行此操作。不幸的是,C#编译器目前不提供宏或等同于____FILE____和____LINE____。

这实际上意味着您唯一的选择是在运行时记录此信息,这意味着要么将繁琐的手动跟踪添加到您要记录的每个方法,要么按照您的描述使用反射命中。

答案 4 :(得分:0)

我认为Log4PostSharp可以很好地完成这项工作。

答案 5 :(得分:0)

如果您关注速度,则应使用Event Tracing for Windows创建实际日志消息。 ETW是一个高速日志库,实现为可从内核模式和用户模式访问的驱动程序。可以动态打开和关闭跟踪。日志记录为应用程序增加了很少的开销。我已经使用ETW在高吞吐量服务器应用程序中实现跟踪。查看NTrace