开发版本中与OutputDebugString相关联的开销

在发布版本中调用OutputDebugString是否有相当大的开销?

测量 – 10M电话大约需要50秒。 我认为这是未使用的功能的重大开销。

使用宏可以帮助摆脱发布版本中的这一点:

#ifdef _DEBUG #define LOGMESSAGE( str ) OutputDebugString( str ); #else #define LOGMESSAGE( str ) #endif 

不仅删除调用,而且参数评估和文本字符串被完全删除,您将不会在二进制文件中看到它们。

在这个问题已经得到回答之后,我正在写这篇文章,但是给出的答案错过了某个方面:

当没有人正在监听输出时,OutputDebugString可以相当快。 但是,让一个监听器在后台运行(比如DbgView,DBWin32,Visual Studio等等)可以使其慢10倍以上(在MT环境中更多)。 原因是这些监听器挂钩了报告事件,并且他们的事件处理是在OutputDebugString调用的范围内完成的。 而且,如果多个线程同时调用OutputDebugString,它们将被同步。 有关更多信息,请参阅注意:DebugView(OutputDebugString)和性能 。

作为一个方面说明,我认为,除非你正在运行实时应用程序,否则你不应该担心需要50秒钟的时间才能运行10M的电话。 如果你的日志包含10M的条目,浪费50秒是你的问题中最少的,现在你必须以某种方式分析这个野兽。 一个10K的日志听起来更加合理,创建这个只需要0.05秒就可以进行锐利的测量。

所以,如果你的输出是在一个合理的大小,使用OutputDebugString不应该伤害你那么多。 但是,请记住一旦系统中的某个人开始监听此输出,就会发生减速。

我曾经在一篇文章中读到OutPutDebugString在内部做了一些有趣的事情:

  1. 创建\打开互斥体,并无限等待,直到获得互斥体。
  2. 在应用程序和调试器之间传递数据是通过一个4k字节的共享内存完成的,Mutex和两个Event对象保护对它的访问。

即使调试器没有连接(在发布模式下),使用OutputDebugstring和使用不同的内核对象也会产生很大的代价。

如果您编写示例代码并进行测试,性能将会非常明显。

多年来,我在几十个服务器端发布模式应用程序中没有遇到任何问题,所有这些都有内置的指标。 你可以得到这样的印象 ,因为大部分的调试捕获器应用程序(DBWIN32等)在将数据上传到屏幕上的速度非常慢,这给人留下了滞后的印象。

当然,我们所有的应用程序默认情况下都禁用了这个输出,但是可以在字段中打开这个输出很有用的,因为您可以查看几个应用程序的调试输出,这些应用程序使用类似于DBWin32的方式进行序列化。 对于涉及通信应用程序的错误,这可能是一个非常有用的调试技术。

在发布版本中不要离开OutputDebugString()调用。 总是使用#ifdef语句删除它们,或者提供另一个开关来关闭它们。

如果你把它们放在里面,默认情况下它们是禁用的,只能根据请求激活它们,因为否则你的应用程序将很难调试其他表现不错的应用程序(即,只根据请求输出调试数据)。

Theres DebugView捕捉应用程序的输出,但当然,这只是如果不是每个应用程序聊天没有很好的理由。

为什么不自己衡量呢? 编译下面的代码,运行它和时间。 然后删除对OutputDebugString的调用,重新编译并重新运行。 应该花三分钟的时间。

  #include <windows.h> int main() { const int COUNT = 1000000; int z = 0; for ( unsigned int i = 0; i < COUNT; i++ ) { z += i; OutputDebugString( "foo" ); } return z; } 

我很好奇这个话题,所以我做了一些研究。

我已经发布了结果,源代码和项目文件,以便您可以重复测试您的设置。 运行发布模式应用程序,无需监视OutputDebugString,然后使用Visual Studio 6,Visual Studio 2005和Visual Studio 2010监视OutputDebugString,查看每个Visual Studio版本的性能差异。

有趣的结果是,Visual Studio 2010处理OutputDebugString信息的速度比Visual Studio 6慢7倍。

在这里完整的文章: OutputDebugString的成本是多少?