5

我一直在试图找出为什么在调试模式下调试我们的程序需要这么长时间。在使用 xperf 查看堆栈的样子后,很明显我们在迭代器和 STL 容器上花费了大量时间。我用谷歌搜索了一段时间并找到了选项

_HAS_ITERATOR_DEBUGGING=0
_SECURE_SCL=0
_SECURE_SCL_THROWS=0

我用#define在代码中设置了所有这些

#define _HAS_ITERATOR_DEBUGGING 0
#define _SECURE_SCL 0
#define _SECURE_SCL_THROWS 0

但这似乎不起作用,所以我尝试使用 Visual Studio 项目中的预处理器定义,但这似乎仍然没有帮助。

我已经尝试了几乎所有我能想到的排列,包括将它们设置在标题中,并且毕竟包含,但无论我做什么,我在调试时都没有看到性能提升。举个例子,在发布模式下运行时,这一系列操作大约需要 140 秒。在调试模式下,它需要 2,400 多秒。处理时间大约增加 17-18 倍。

一些附加信息,托管这些 C++ dll 的进程是 C# .net 4 进程,并且我启用了非托管代码调试。基本上所有的过程都会为我们加载 DLL。所有真正的工作都是在 c++ 代码中完成的。

我在下面包含了完整的编译器命令行。

/I"..\CommonInclude" /Zi /nologo /W4 /WX /Od /Oy- /D "_CRT_SECURE_NO_WARNINGS" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "ENGINE_EXPORTS" /D "_HAS_ITERATOR_DEBUGGING=0" /D "_SECURE_SCL=0" /D "_SECURE_SCL_THROWS=0" /D "_VC80_UPGRADE=0x0710" /D "_WINDLL" /D "_MBCS" /Gm- /EHa /MDd /GS /fp:precise /Zc:wchar_t- /Zc:forScope /GR /Yu"StdAfx.h" /Fp".\Debug/Foo.pch" /Fa".\Debug/" /Fo".\Debug/" /Fd".\Debug/" /Gd /analyze- /errorReport:queue /EHa -Zm350 /MP3 

有什么想法为什么会这么慢?

4

3 回答 3

7

根据您的描述,这会立即跳出:

我一直在试图找出为什么在调试模式下调试我们的程序需要这么长时间。在使用 xperf 查看堆栈的样子后,很明显我们在迭代器和STL 容器上花费了大量时间。

如果您使用基于节点的容器(例如,mapsetunordered_mapunordered_setmultimapmultisetlist等)并从调试器运行,您可能会遇到源于这些容器分配大量小尺寸对象的问题。当您从 Windows 中的调试器运行应用程序时,操作系统会将进程堆切换到调试堆。如果您有许多基于节点的容器处于负载状态,则释放它们将占用调试堆的大量时间。

一个简单的修复方法是通过将以下内容添加到调试选项的环境部分来禁用调试堆:_NO_DEBUG_HEAP=1

这将禁用调试堆。

于 2012-05-15T22:37:10.887 回答
1

有几件事可以尝试:

  • 使用分析器,例如免费的AMD CodeAnalyst,因为它会为您提供调用堆栈,并且通常比 Xperf 更易于使用。即使您正在处理调试代码,您仍然可能会发现一些热点
  • 创建一个关闭优化的发布版本(您可以为此创建一个单独的配置)。这将关闭迭代器调试(如果这是您减速的原因),但可能会提供比原始版本构建更有用的调试信息。检查是否启用了省略帧指针的选项
于 2012-05-15T22:24:12.803 回答
1

产生巨大差异的一件事是,默认情况下,函数不会在调试模式下内联。这为使用许多小型访问器函数的代码增加了大量时间。

我有一些程序,其中调试和发布模式之间的差异是 100+ 倍,而不依赖于迭代器。

于 2012-05-15T21:53:20.913 回答