我应该在 #if(DEBUG)中包装对Debugger.Log()的调用吗?

本文关键字:Log 调用 Debugger 包装 #if DEBUG 我应该 | 更新日期: 2023-09-27 18:36:44

出于

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

我应该在 #if(DEBUG)中包装对Debugger.Log()的调用吗?

RELEASE 模式下,调用没有任何优化。

调用存在于 IL 中。唯一的区别是,如果没有调试器,它没有任何影响。

来自文档 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 调用不会执行任何操作并快速返回。 您只需为函数调用开销付费,只需几纳秒。

方法调用没有任何像样的优化,无论您构建调试还是发布配置,它的执行方式都相同。 在发布版本中访问调试信息当然很方便,由你决定是否要关闭该功能。 很难说这些纳秒是否对你的程序有可观察到的影响。 测量,不要假设任何事情。

以下代码的快速测试(.NET 4、版本、任何 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