【发布时间】:2009-04-08 10:47:56
【问题描述】:
在发布版本中调用 OutputDebugString 是否存在重大开销?
【问题讨论】:
标签: windows performance winapi logging
在发布版本中调用 OutputDebugString 是否存在重大开销?
【问题讨论】:
标签: windows performance winapi logging
实测 - 1000 万次调用大约需要 50 秒。我认为这对于未使用的功能来说是很大的开销。
使用宏可以帮助在发布版本中摆脱这种情况:
#ifdef _DEBUG
#define LOGMESSAGE( str ) OutputDebugString( str );
#else
#define LOGMESSAGE( str )
#endif
不仅删除了调用,还完全删除了参数评估和文本字符串,您不会在二进制文件中看到它们。
【讨论】:
我在回答这个问题很久之后才写这篇文章,但给出的答案错过了某个方面:
当没有人监听它的输出时,OutputDebugString 可以非常快。然而,在后台运行一个监听器(无论是 DbgView、DBWin32、Visual Studio 等)可以使它慢 10 倍以上(在 MT 环境中要慢得多)。原因是这些侦听器挂钩了报告事件,并且它们对事件的处理是在 OutputDebugString 调用的范围内完成的。此外,如果多个线程同时调用 OutputDebugString,它们将被同步。更多信息,请参阅Watch out: DebugView (OutputDebugString) & Performance。
作为旁注,我认为除非您正在运行实时应用程序,否则您不应该担心需要 50 秒才能运行 1000 万次调用的设施。如果您的日志包含 10M 条目,那么浪费的 50 秒是您的问题中最少的,因为您必须以某种方式分析野兽。 10K 的日志听起来要合理得多,根据Sharptooth 的测量,创建它只需0.05 秒。
因此,如果您的输出在合理的大小范围内,使用 OutputDebugString 应该不会对您造成太大伤害。但是,请记住,一旦系统上有人开始收听此输出,就会出现减速。
【讨论】:
我在一篇文章中读到 OutPutDebugString 在内部做了一些有趣的事情:
即使没有附加调试器(在发布模式下),在使用 OutputDebugstring 和各种内核对象时也会产生大量成本。
如果您编写示例代码并进行测试,性能会非常明显。
【讨论】:
多年来,我在数十个服务器端发布模式应用程序中没有发现任何问题,所有这些应用程序都具有内置指标。您可能会得到印象,因为您可以找到的大多数调试捕获应用程序(DBWIN32 等)在将数据投射到屏幕上时都非常缓慢,这给人一种滞后的印象。
当然,我们所有的应用程序都默认禁用此输出,但能够在现场打开它很有用,因为您可以查看多个应用程序的调试输出,序列化在 DBWin32 之类的东西中。对于涉及通信应用程序的错误,这可能是一种非常有用的调试技术。
【讨论】:
永远不要在发布版本中留下 OutputDebugString() 调用。始终使用#ifdef 语句删除它们,或者提供另一个开关来关闭它们。
如果您将它们保留在其中,则默认禁用它们并仅在请求时激活它们,否则您的应用将难以调试其他表现良好的应用(即仅在请求时输出调试数据)。
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 倍。
【讨论】:
现有答案可以追溯到 2009 / 2010 年。
虽然被遗忘的 OutputDebugString() 的性能可能没有太大变化,但我可以看出该工具有很大的不同。
结论:
原来的 DebugView 太慢了,我减少了样本的数量以便在某个时候真正完成。
DebugView++ 做得非常好。
VS 2019 似乎比旧版 Visual Studio 做得更好,提到 in this answer。我无法比较自己,但它与 DebugView++ 非常接近,我认为它非常好。
测量结果:在单个 for 循环中调用了 100.000 次 OutPutDebugStringW。发布模式下的所有构建。 Intel i7-6820HQ,2.7 GHz,限制为 99% 以防止 Turbo Boosting。使用std::chrono::high_resolution_clock::now() 在 100.000 次调用之前和之后进行测量。
【讨论】: