10

是否有必要Debugger.Log()#if (DEBUG)预处理器指令中包装调用以进行代码优化,还是 C# 编译器在构建RELEASE配置时仍会生成优化代码?

4

3 回答 3

5

在RELEASE模式下,调用没有任何类型的优化。

呼叫出现在IL. 唯一的区别是如果没有DEBUGGER存在,它没有任何效果。

从文档Debugger.Log

如果没有附加调试器,则此方法无效。

我建议衡量您的应用程序的性能,然后选择要遵循的步骤。

如果没有显着差异(从您的应用程序的角度来看),我会保留该日志。

这样,在需要的时候,您可以使用调试器附加到您的应用程序,并从日志中获取您可能需要的消息,就像Debugger.Log那时那样

于 2012-06-11T14:03:53.593 回答
1

这是 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 配置,它都会以相同的方式执行。在发布版本中访问调试信息当然很方便,您可以决定是否要关闭该功能。很难说这些纳秒是否对您的程序有明显的影响。衡量,不要假设任何事情。

于 2012-06-11T14:55:06.777 回答
0

以下代码的快速测试(.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.

于 2012-06-11T14:12:50.577 回答