是否有必要Debugger.Log()
在#if (DEBUG)
预处理器指令中包装调用以进行代码优化,还是 C# 编译器在构建RELEASE
配置时仍会生成优化代码?
3 回答
在RELEASE模式下,此调用没有任何类型的优化。
呼叫出现在IL
. 唯一的区别是如果没有DEBUGGER存在,它没有任何效果。
从文档Debugger.Log:
如果没有附加调试器,则此方法无效。
我建议衡量您的应用程序的性能,然后选择要遵循的步骤。
如果没有显着差异(从您的应用程序的角度来看),我会保留该日志。
这样,在需要的时候,您可以使用调试器附加到您的应用程序,并从日志中获取您可能需要的消息,就像Debugger.Log
那时那样。
这是 Debugger.Log() 的声明,从参考源中检索到:
// Posts a message for the attached debugger. If there is no
// debugger attached, has no effect. The debugger may or may not
// report the message depending on its settings.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void Log(int level, String category, String message);
请注意,该方法没有 [Conditional] 属性,它带有 [MethodImplAtttribute] 属性。这意味着该方法实际上是在 CLR 中实现的,用 C++ 代码编写。
因此,无论配置如何,都会进行方法调用。您可以从 SSCLI20 源代码分发版 clr/src/vm/debugdebugger.cpp 中找到该方法的实现。它使用 OutputDebugString(),这是一个在调试器中显示字符串的 winapi 函数(如果附加了字符串)。或者在像 SysInternals 的 DbgView.exe 这样的实用程序中。如果两者都不存在,则 api 调用什么也不做,并迅速返回。您只需支付函数调用开销,几纳秒。
方法调用没有什么值得优化的地方,无论您构建 Debug 还是 Release 配置,它都会以相同的方式执行。在发布版本中访问调试信息当然很方便,您可以决定是否要关闭该功能。很难说这些纳秒是否对您的程序有明显的影响。衡量,不要假设任何事情。
以下代码的快速测试(.NET 4、Release、Any CPU)
class Program
{
static void Main(string[] args)
{
#if (DEBUG)
Debugger.Log(0, "category", "msg");
#endif
}
}
产生这个 IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 8
L_0000: ret
}
如您所见,没有调用Debugger.Log
.