我基本上想编写一个客户记录器/跟踪器,它还记录调用记录器/跟踪器的方法的类和方法名称。这应该很快,这样它不会影响应用程序的性能,强类型和清洁。有没有人有好主意?
以下是我所拥有的一些,但我担心由于反思而导致的表现:
StackTrace / StackFrame(开销太大了?)
MethodInfo.GetCurrentMethod()(还是太慢了?而且不是很干净)
传递方法作为委托(C#可以隐式执行,我可以访问MethodInfo,但不是很干净)
我感谢任何人的评论。
更新
我喜欢StackFrame的无尘,所以我就StackFrame的性能提出了一个更具体的问题here,我得到了一些非常好的响应,包括性能测试。事实证明,MethodInfo.GetCurrentMethod()
是最快的(在我的计算机上大约需要1微秒),new StackFrame(1)
可以按需请求(在我的计算机上大约需要15-20微秒)。我将该方法作为委托选项抛出,因为当方法有多个参数时它太乱了。
结论:
我已经查看了所有选项,最好的是为PostSharp编写一个自定义插件,在编译时将方法名称作为字符串注入到MSIL中,同时应用[Trace]
等自定义属性。在我看来,这是最快,最易维护的选择。这甚至可以实现更多的事情,比如传递参数名称和参数而不需要任何反射,并自动捕获和记录异常。这个my related question了解更多信息。
答案 0 :(得分:4)
最快的方法是在编译时这样做,这是事实,但在.NET中最方便的方法是使用CallerMemberName,CallerFilePath和其他编译器服务属性在.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。