为啥附加到调试器的运行如此缓慢?

Posted

技术标签:

【中文标题】为啥附加到调试器的运行如此缓慢?【英文标题】:Why is running attached to the debugger so slow?为什么附加到调试器的运行如此缓慢? 【发布时间】:2012-03-06 22:22:12 【问题描述】:

与未附加的相比,附加到调试器的调试构建速度要慢得多,这是怎么回事?它们都是同一个运行的 exe。

编辑:大多数答案都集中在断点上。我仍然在没有断点、OutputDebugString 或监视窗口中的任何内容的情况下像泥巴一样运行。调试 CRT、运行时堆栈检查和调试堆呢?

【问题讨论】:

您的内存不足和磁盘垃圾了吗? 【参考方案1】:

如果不是OutputDebugString 或成堆的断点使一切变慢,请尝试以下方法:

Windows 调试堆 - 如果您的进程在调试器下运行,您的进程将获得调试堆,无需询问任何问题。要在 Visual Studio 调试器下运行时禁用此功能,请访问项目属性的调试页面并将_NO_DEBUG_HEAP=1 添加到环境中。

(Windows 调试堆与 CRT 调试堆是分开的。如果在调试器下运行,您的发布版本也将获得 Windows 调试堆。)

该程序会加载大量具有符号的 DLL。加载 DLL 时,Visual Studio 会尝试为其查找符号。如果有可用的符号,这可能需要一些时间。除了重新排列程序以减少加载 DLL 的频率之外,您对此无能为力。

检查对 IsDebuggerPresent 的任何调用 - 这可能会在调试器内外运行之间引入任意差异。

(作为最后的一次性建议 - 我也怀疑异常(无论是 C++ 还是结构化)在调试过程时可能会涉及更多。因此,如果您的程序抛出很多,也许这可能有点调试时速度较慢。)

【讨论】:

关于_NO_DEBUG_HEAP=1的优秀文章preshing.com/20110717/…【参考方案2】:

如果您的调试器使用软件观察点,它会在内部单步执行代码并检查这些点和变量值的变化。

[VS] 调试器只能支持 4 个硬件数据断点。如果你使用 表达式 (a + b),调试器使用仿真模式。

此外,加载库的调试信息速度较慢,并且会增加感知执行时间(响应时间)。

Reference

【讨论】:

你能链接你的来源吗?我想阅读那里写的其余内容。谢谢 我不相信!单步执行代码会执行得很糟糕,以至于调试器将毫无用处。你确定吗?单步执行意味着对于每条指令,都会生成一个陷阱,操作系统内核必须处理该陷阱。该代码将像在 1981 年的 4.77 Mhz IBM PC 上一样运行。:) 我从未见过 VS 调试器的性能如此糟糕。我认为/希望软件断点可以通过用断点陷阱类型指令(如 x86 上的 int $3)替换断点指令的明显方法来实现。 啊,你说的是数据断点;对不起。 :) ^sheepish^【参考方案3】:

您是否有大量通过 OutputDebugString 进行的日志记录? OutputDebugString 生成的输出由调试器接收,但在不在调试器下运行时会被忽略。

【讨论】:

此项目中没有,但这是我上一个项目中的主要性能问题。【参考方案4】:

有几个原因导致在附加调试器的情况下运行比不附加调试器运行速度要慢得多。最可能的原因是

断点数量过多 具有昂贵条件的断点 跟踪点过多

首先要尝试禁用所有断点并查看其对性能的影响

【讨论】:

禁用断点确实有所作为,但附加的仍然比未附加的慢约 3 倍。

以上是关于为啥附加到调试器的运行如此缓慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我无法将调试器附加到已签名的 apk 进程?

为啥要等待调试器,然后将调试器附加到进程?

远程调试,附加到尚未启动的进程

vs2017 调试附加进程 结束进程为啥很卡慢

为啥 Docker 构建命令在 Elastic Beanstalk 中运行如此缓慢?

为啥我的 Apps 脚本删除循环运行如此缓慢?我可以提高性能吗?