在发布版本中与OutputDebugString关联的开销

时间:2009-04-08 10:47:57

标签: windows performance winapi logging

在发布版本中调用OutputDebugString会产生很大的开销吗?

8 个答案:

答案 0 :(得分:15)

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

使用宏可以帮助在发布版本中摆脱这个:

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

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

答案 1 :(得分:11)

在这个问题得到解答之后,我写这篇文章的时间很长,但给定的答案错过了某个方面:

当没有人正在监听其输出时,OutputDebugString可以非常快。但是,让一个监听器在后台运行(无论是DbgView,DBWin32,Visual Studio等)都可以使它慢10倍以上(在MT环境中更多)。原因是这些侦听器挂钩了报表事件,并且它们对事件的处理是在OutputDebugString调用的范围内完成的。此外,如果多个线程同时调用OutputDebugString,它们将被同步。有关更多信息,请参阅Watch out: DebugView (OutputDebugString) & Performance

作为旁注,我认为除非您正在运行实时应用程序,否则您不应该担心需要50秒才能运行10M呼叫的设施。如果您的日志包含10M条目,那么浪费的50秒是您遇到的问题中最少的,现在您必须以某种方式分析该野兽。一个10K的日志听起来更合理,根据sharptooth的测量创建只需0.05秒。

因此,如果您的输出在合理的大小范围内,使用OutputDebugString不会对您造成太大伤害。但是,请记住,一旦系统中的某人开始收听此输出,就会发生减速。

答案 2 :(得分:9)

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

  1. 创建\打开互斥锁并无限期等待,直到获得互斥锁。
  2. 在应用程序和调试器之间传递数据是通过一个4k字节的共享内存块完成的,其中有一个Mutex和两个Event对象来保护对它的访问。
  3. 即使没有附加调试器(在发布模式下),使用OutputDebugstring和使用各种内核对象也会产生很大的成本。

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

答案 3 :(得分:8)

多年来,我没有在数十个服务器端发布模式应用程序中看到任何问题,所有这些应用程序都具有内置指标。您可以获得印象它很慢,因为您可以找到的大多数调试捕获器应用程序(DBWIN32等)在将数据投放到屏幕上的速度非常慢,这给人一种滞后的印象。

当然,我们的所有应用程序默认都禁用此输出,但 对于能够在字段中打开它是有用的,因为您可以查看来自多个应用程序的调试输出,序列化像DBWin32这样的东西。对于涉及通信应用程序的错误,这可能是一种非常有用的调试技术。

答案 4 :(得分:6)

永远不要在发布版本中留下OutputDebugString()调用。始终使用#ifdef语句删除它们,或者提供另一个开关以关闭它们。

如果你把它们留下来,默认情况下禁用它们并且只在请求时激活它们,否则你的应用程序将很难调试其他表现良好的应用程序(即,仅根据请求输出调试数据)。

Theres DebugView来抓住应用程序的输出,但当然,如果不是每个应用程序都没有充分的理由,那就是好的。

答案 5 :(得分:4)

为什么不亲自测量?编译以下代码,运行它&时间吧。然后删除对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;
    }

答案 6 :(得分:2)

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

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

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

全文:Whats the cost of OutputDebugString?

答案 7 :(得分:0)

现有答案可以追溯到2009年/ 2010年。

虽然被遗忘的OutputDebugString()的性能可能没有太大变化,但我可以看出该工具产生了巨大的变化。

  • 没有工具:30 µs /调用(x86)10 µs /调用(x64)
  • DebugView(完全禁用):64 µs /通话(x86)37 µs /通话(x64)
  • DebugView++(已暂停):67 µs(x86)
  • DebugView(停用自动滚动):735 µs /调用(x86)703 µs /调用(x64)
  • DebugView ++(停用自动滚动):67 µs /调用
  • DebugView(自动滚动激活):936 µs(x86)799 µs /调用(x64)
  • DebugView ++(自动滚动激活):67µs /调用
  • VS 2019:81 µs /调用
  • DebugView(同步2个实例):最多1736 µs /调用
  • DebugView ++(同步2个实例):每次调用高达102µs

结论:

原始的DebugView是如此之慢,以至于我减少了实际完成采样的数量。

DebugView ++做得非常好。

{p> 3提到,

VS 2019似乎比旧的Visual Studio更好。我无法比较自己,但是它在DebugView ++上是如此接近,我认为它真的很棒。


测量:在单个for循环中100.000次OutPutDebugStringW调用。所有版本均以发布模式构建。英特尔i7-6820HQ(2.7 GHz)限制为99%,以防止Turbo Boosting。在100.000次通话之前和之后使用std::chrono::high_resolution_clock::now()进行测量。