为什么即使将_HAS_ITERATOR_DEBUGGING、_SECURE_SCL、_SECURE_SCL_THROWS设置为0,迭代器在VS2010中仍然导致非常缓慢的调试?

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 进程,并启用了非托管代码调试。基本上,所有的工作都是在 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 

有什么原因导致它如此缓慢吗?

这是一个调试版本,旨在进行调试而非优化性能。它的目的是确保您的代码正常运行。 - Nicol Bolas
迭代器调试并不那么慢。没有优化代码更可能是原因。解决方法很简单,只需使用较小的数据集验证您的代码。使用一百倍的数据来排除错误的几率并不是很大。 - Hans Passant
3个回答

7
根据你的描述,立即显而易见的问题是:在调试模式下调试我们的程序为什么需要这么长时间。通过使用xperf查看栈的情况后,很明显我们花费了大量的时间在迭代器和STL容器中。如果您使用基于节点的容器(例如map、set、unordered_map、unordered_set、multimap、multiset、list等),并从调试器运行,可能会遇到这些容器分配大量具有小尺寸的对象所导致的问题。在Windows中从调试器运行应用程序时,操作系统将进程堆切换到调试堆。如果负载下有多个基于节点的容器,释放它们将花费大量时间与调试堆。一个简单的解决方法是通过在调试选项的Environment部分添加以下内容来禁用调试堆:_NO_DEBUG_HEAP=1。这将禁用调试堆。

1

有一件事情可以产生巨大的影响,那就是在调试模式下默认情况下函数不会被内联。这会给使用许多小的访问器函数的代码添加很多时间。

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


1

尝试以下几点:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接