为什么条件断点会使我的程序速度减慢这么多?

发布于 2024-07-30 12:14:56 字数 140 浏览 3 评论 0原文

当我调试循环内出错的地方时,比如在第 600 次迭代时,必须对每个循环进行中断可能会很痛苦。 因此,我尝试设置一个条件断点,仅在 I = 600 时才中断。这可行,但现在几乎需要一整分钟才能到达该点,而在此之前几乎是瞬时的。 这是怎么回事,有什么办法可以解决吗?

When I'm debugging something that goes wrong inside a loop, say on the 600th iteration, it can be a pain to have to break for every one. So I tried setting a conditional breakpoint, to only break if I = 600. That works, but now it takes almost a full minute to reach that point, where before it was almost instantaneous. What's going on, and is there any way to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

生生漫 2024-08-06 12:14:56

当您遇到断点时,Windows 会停止该进程并通知调试器。 它必须切换上下文,评估条件,决定不,您不想收到有关它的通知,重新启动进程并切换回来。 这可能需要很多处理器周期。 如果您在紧密循环中执行此操作,则所需的处理器周期将比循环的一次迭代多几个数量级。

如果您愿意稍微修改一下代码,有一种方法可以在不产生所有这些开销的情况下执行条件断点。

if <condition here> then
  asm int 3 end;

这是一个简单的汇编指令,手动向操作系统发送断点通知。 现在您可以在程序内评估您的状况,而无需切换上下文。 只要确保用完后再次将其取出即可。 如果 int 3 在未连接到调试器的程序内发生,它将引发异常。

When you hit a breakpoint, Windows stops the process and notifies the debugger. It has to switch contexts, evaluate the condition, decide that no, you don't want to be notified about it, restart the process and switch back. That can take a lot of processor cycles. If you're doing it in a tight loop, it'll take a couple orders of magnitude more processor cycles than one iteration of the loop takes.

If you're willing to mess with your code a little, there's a way to do conditional breakpoints without incurring all this overhead.

if <condition here> then
  asm int 3 end;

This is a simple assembly instruction that manually sends a breakpoint notification to the OS. Now you can evaluate your condition inside the program, without switching contexts. Just make sure to take it out again when you're done with it. If an int 3 goes off inside a program that's not connected to a debugger, it'll raise an exception.

呢古 2024-08-06 12:14:56

它会减慢速度,因为每次您到达该点时,它都必须检查您的状况。

我倾向于做的是临时创建另一个像这样的变量(在 C 中,但在 Delphi 中应该可行)。

int xyzzynum = 600;
while (true) {
    doSomething();
    if (--xyzzynum == 0)
        xyzzynum = xyzzynum;
}

然后我在 "xyzzynum = xyzzynum;" 行上放置一个非条件断点。

程序全速运行,直到循环了 600 次,因为调试器只是执行正常的断点中断,而不是每次都检查条件。

您可以根据需要使条件变得复杂。

It slows it down because every time you reach that point, it has to check your condition.

What I tend to do is to temporarily create another variable like this (in C but should be doable in Delphi).

int xyzzynum = 600;
while (true) {
    doSomething();
    if (--xyzzynum == 0)
        xyzzynum = xyzzynum;
}

then I put a non-conditional breakpoint on the "xyzzynum = xyzzynum;" line.

The program runs at full speed until it's been through the loop 600 times, because the debugger is just doing a normal breakpoint interrupt rather than checking conditions every time.

You can make the condition as complicated as you want.

叶落知秋 2024-08-06 12:14:56

根据 Mason 的回答,您可以仅在程序是使用定义的调试条件构建的情况下编译 int 3 汇编:

{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
  asm int 3 end;
{$endif}

因此,当您在 ide 中进行调试时,您可以在项目选项中使用调试条件。 当您为客户构建最终产品时(使用构建脚本?),您不会包含该符号,因此它不会被编译。

我还包含了 $message 编译器指令,因此您在编译时会看到警告让您知道该代码仍然存在。 如果您在使用 int 3 的任何地方都这样做,那么您将获得一个很好的位置列表,您可以双击该列表直接进入有问题的代码。

氮@

Further to Mason's answer, you could make the int 3 assember only be compiled in if the program is built with the debug conditional defined:

{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
  asm int 3 end;
{$endif}

So, when you are debugging in the ide, you have the debug conditional in the project options. When you build the final product for your customers (with your build script?), you wouldn't include that symbol, so it wont get compiled in.

I also included the $message compiler directive, so you will see a warning when you compile letting you know that the code is still there. If you do that everywhere you use int 3, you will then have a nice list of places which you can double click on to take you straight to the offending code.

N@

初心 2024-08-06 12:14:56

Mason的解释非常好。
通过测试您在调试器下运行,可以使他的代码更安全

if (DebugHook <> 0) and <your specific condition here> then
  asm int 3 end;

当应用程序正常运行时,这不会执行任何操作,并且如果它在调试器下运行(无论是从调试器启动),它将停止IDE 或附加到调试器)。
如果您不在调试器下,则使用布尔快捷方式<您的具体条件>甚至不会被评估。

Mason's explanations are quite good.
His code could be made a bit more secure by testing that you run under the debugger:

if (DebugHook <> 0) and <your specific condition here> then
  asm int 3 end;

This will not do anything when the application is running normally and will stop if it's running under the debugger (whether launched from the IDE or attached to the debugger).
And with boolean shortcut <your specific condition here> won't even be evaluated if you're not under the debugger.

空心↖ 2024-08-06 12:14:56

任何调试器中的条件断点(我只是在这里猜测)都要求每次遇到断点时,进程都会在程序和调试器之间来回翻转。 这个过程很耗时,但我认为你无能为力。

Conditional breakpoints in any debugger (I'm just surmising here) require the process to flip back and forth every time between your program and the debugger every time the breakpoint is hit. This process is time consuming but I do not think there is anything you can do.

笑咖 2024-08-06 12:14:56

通常,条件断点的工作原理是在代码中插入适当的中断指令,然后检查您指定的条件。 它会在每次迭代时进行检查,并且很可能是检查的实现方式造成了延迟,因为调试器不太可能编译完整的检查和断点代码并将其插入到现有代码中。

可以加速这一过程的一种方法是,将条件后跟一个没有副作用的操作直接放入代码中,并在该操作上中断。 只需记住在完成后删除条件和操作即可。

Normally condition breakpoints work by inserting the appropriate break instruction into the code and then checking for the conditions you have specified. It'll check at every iteration and it might well be that the way in which the check is implemented is responsible for the delay as it's unlikely that the debugger compiles and inserts the complete check and breakpoint code into the existing code.

A way that you might be able to accelerate this is if you put the condition followed by an op with no side effect into the code directly and break on that op. Just remember to remove the condition and the op when you're done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文