我有一个本地的C++程序,当使用 Debug(F5)启动时,运行速度会变慢超过20倍;但当使用不带调试的启动方式(Ctrl+F5),则速度正常。
无论我使用debug还是release构建都没有影响。同时,如果我使用WinDbg,则该程序的运行速度会变得非常慢。
是否有某些设置选项我选择错误了,还是其他原因呢?
我有一个本地的C++程序,当使用 Debug(F5)启动时,运行速度会变慢超过20倍;但当使用不带调试的启动方式(Ctrl+F5),则速度正常。
无论我使用debug还是release构建都没有影响。同时,如果我使用WinDbg,则该程序的运行速度会变得非常慢。
是否有某些设置选项我选择错误了,还是其他原因呢?
将_NO_DEBUG_HEAP环境变量设置为1(如http://preshing.com/20110717/the-windows-heap-is-slow-when-launched-from-the-debugger中所示)。
这也可以在Visual Studio内完成。
现在,这只是一个解决方法,我很想知道如何重构遭受此类问题的程序。 你是否碰巧有许多std :: map、shared_ptr或任何其他大的间接引用?
当然,这并不是由于定义了_DEBUG符号或在调试配置中编译代码所导致的。添加的调试代码无论是否连接到程序都会运行。
调试器通常不影响代码执行,通过调用WaitForDebugEvent来保持远离程序。此操作将阻塞它,直到操作系统告诉它发生了值得注意的事情。这可能会触发调试器中的一系列代码,从而减慢程序速度。您可以在DEBUG_EVENT结构文档中查看事件列表。
稍微注释一下文档之外的内容:当以下事件发生时,调试器将介入并可能会减慢程序速度:
程序加载或卸载DLL。在加载期间会发生很多事情,调试器会寻找一个调试符号文件(.pdb)。它可能会联系符号服务器以下载它。任何在DLL源代码中设置的断点都将被激活。这可能会相当缓慢,但效果是暂时的,并且通常只会减慢启动。您可以在“输出”窗口中看到加载/卸载通知。
程序引发异常。这会在引发异常时立即激活调试器,即“第一次机会通知”。这可能非常有帮助,您可以使用“调试”+“异常”、“抛出”复选框,使调试器在引发异常时停止。您可以在“输出”窗口中看到通知消息。这会大大减慢引发并捕获异常的代码,并很可能是减慢程序速度的源头。不要使用异常进行流程控制。
线程开始运行或终止。再次,在“输出”窗口中打印有通知消息。如果想通过此方式减速程序,则必须创建许多线程。
当程序使用OutputDebugString()进行跟踪时。在“输出”窗口中可见。这是减缓速度的另一种好选择,如果没有连接到调试器,则输出将被忽略。您不应该有任何麻烦来诊断它作为导致问题的原因,明显的副作用是在“输出”窗口中看到大量的消息。
当程序遇到断点时,通常不会引起困惑。但是有些断点会使程序变慢,却不会导致调试器中断。特别是条件断点、击中计数器、过滤器和击中操作会很慢。请使用“调试”+“窗口”+“断点”来查看定义的断点。
printf()
语句也需要很长时间才能完成。VS直到执行几分钟后才显示“正在加载…”对话框,这就使一切变得如此缓慢显而易见。 - huoneusto/ZI
改为/Zi
。有关说明,请参见MSDN页面。如果您在IDE之外运行调试版本,则有几个不同的事情。其中一个是IDE需要一段时间来加载符号,如果您依赖许多库,则启动时间可能会很长。
如果您使用符号服务器(包括Microsoft公共符号服务器),则这可能会增加启动时间,因此请确保在_NT_SYMBOL_PATH
变量中具有本地符号缓存。
此外,IDE启用了调试堆,但我认为如果您在IDE之外运行,则不会发生这种情况。
调试 Visual C++ 带来了很多开销,特别是在 STL 中。尝试不定义 _DEBUG
,并定义 NDEBUG
。