Visual Studio - 条件断点和禁用断点对运行时的影响

发布于 2024-08-08 10:15:22 字数 353 浏览 6 评论 0原文

在花了一些时间想知道为什么我的应用程序在附加调试器的情况下运行特定场景非常缓慢之后,我发现这是由于有一个条件断点(其条件从未得到满足)。这似乎是合理的,因为 CPU 会发出断点信号,而 VS 需要在允许继续执行之前评估条件。这些转变必定代价高昂。

我假设未执行的代码路径中的断点不会对运行时产生影响。

所以我的问题是双重的:

  1. 是否有任何资源可以量化与条件断点相关的成本,如果有的话,可以做些什么来减少运行时评估成本?
  2. “禁用”断点是否会产生任何相关成本?我所说的禁用是指 VS 在装订线中显示带有空心圆的断点标记。

当然,如果我上面提到的任何内容没有意义,那么请为我指出正确的方向。

After spending a little time wondering why my app was running a particular scenario very slowly with the debugger attached, I discovered that this was due to having a conditional breakpoint (whose condition was never being met). This seems reasonable, as the CPU would signal the breakpoint and VS would need to evaluate the condition before allowing execution to continue. These transitions must be costly.

I assume that a breakpoint in a code path that is not executed has no runtime impact.

So my question is twofold:

  1. Are there any resources that can quantify the cost associated with conditional breakpoints, and if so is there anything one can do to reduce their runtime evaluation cost?
  2. Is there any cost associated with a 'disabled' breakpoint? By disabled I mean that VS displays the breakpoint marker in the gutter with a hollow circle.

Of course if anything I've mentioned above doesn't make sense, then please point me in the right direction.

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

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

发布评论

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

评论(5

你的笑 2024-08-15 10:15:22

很难量化条件断点的成本。条件断点中的表达式的计算使用完全相同的语义,就像您将其输入到监视或立即窗口中一样。这种性质的表达式实际上并不在客户端程序中执行,而是由特定于语言的表达式求值器处理。以有意义的方式描述这些类型的评估实际上是不可能的。

不过,我可以列出一些已知在调试窗口中较慢的事情 eval

  • 函数调用:它们是您可以做的最慢的事情,因为函数调用需要重新启动调试进程,以便 func eval 可以在该进程中发生
  • 字符串比较:在幕后,这些会返回到 func evals

至于禁用的断点,不,它们不会影响应用程序的运行。

It's hard to quantify the cost of a conditional breakpoint. The expression in a conditional breakpoint is evaluated using the exact same semantics as if you had typed it into the watch or immediate window. Expressions of this nature are not actually executed in the client program but instead handled by the language specific expression evaluator. It's not really possible to profile these types of evaluations in a meaningful way.

However I can list a few things that are known to be slower in a debug window eval

  • Function Calls: They are the slowest thing you can do because the function call requires the debuggee process to be restarted so that the func eval can occur in the process
  • String comparison: Under the hood these go back to func evals

As for disabled breakpoints, no they do not affect the running of the application.

浪荡不羁 2024-08-15 10:15:22

需要注意的一件事(我通过艰难的方式学到了这一点)是确保在将变量与值进行比较时放置 == 而不是单个 =

断点编辑器不会警告您,但是当评估断点时,变量被改变了!我花了一些时间来调试我的代码!

另外,如果我真的需要条件断点来调试代码;我将条件添加到代码中,然后添加类似 string stop = "here"; 的内容并在那里放置一个正常的断点 - 我发现代码运行得更快。

One thing to watch out for (which I learned the hard way) is to make sure you put == when comparing a variable to a value and not the single =

The breakpoint editor doesn't warn you but when the breakpoint is evaluated, the variable is altered! Took me a while to debug my code with that one!

Also, if I really need the conditional breakpoint to bebug code; I add the condition to the the code, then add something like string stop = "here"; and put a normal breakpoint there - I find the code runs faster then.

玉环 2024-08-15 10:15:22

我在某处读到,这些断点有硬件支持,因此使用少于 x 个某种条件断点基本上是免费的,但除此之外,它需要使用更多的软件。 (OTOH,那是针对本机应用程序的,不确定这些新奇的 JIT 事物。)

禁用的断点应该会影响所有事情,它们只是在 IDE 中占用一些内存和 GUI 资源。

I read somwhere that there is hardware support for these breakpoints, so that using fewer than x conditional breakpoints of a certain kind is essentially free, but above that, it needs to use more software. (OTOH, that was for native apps, not sure about these newfangled JIT things.)

Disabled breakpoints should take affect things at all, they just occopy some memory and GUI resources in IDE.

慕烟庭风 2024-08-15 10:15:22

我还注意到条件断点的成本很高,并且得出了与您相同的结论。我无法想象禁用断点会导致速度减慢的任何原因,因为我希望它只是编辑器的东西,是在需要时打开断点的快捷方式。

当我遇到像你这样的情况时,我所做的就是创建一个断言宏。 (您可以使用 Visual Studio 提供的 assert 宏,但我不喜欢)。让您的宏检查所需的条件,然后调用 DebugBreak< /a> 如果失败。在应用程序的发布或非检查构建中,将断言评估为空,因此您的代码不会受到影响。

一个简单的断言宏可以如下所示:

#ifdef _DEBUG
#define assert(x)\
do{\
  if(!(x)){DebugBreak();}\
}while(0)
#else
#define assert(x)
#endif

并这样调用它:

assert(pValue != NULL && "A bad parameter was passed to the function");

您可以在 DebugBreak 之前在失败中放入更多代码(例如使用 #x 打印失败的条件,和/或使用 ____FILE____ 和 ____LINE____ 打印出失败的条件,这样您就可以双击该消息)。您可以使用 OutputDebugString 甚至检查调试器是否附加了 IsDebuggerPresent 进一步定制您的断言。我也喜欢使用 &&字符串格式以提供有关特定断言的更多信息。

使用assert时有几点需要注意。首先,不要将任何必须在宏中运行的代码放入宏中,因为它将在非调试版本中被删除。出于同样的原因,不要放入有副作用的代码。此外,您不希望在未附加调试器时调用 DebugBreak(),因为它本质上会引发异常,如果未捕获该异常,则会终止应用程序。

I have also noticed that conditional breakpoints are expensive and came to the same conclusion as you. I can't imagine any reason that a disabled breakpoint would cause any slowdown since I would expect it to be an editor only thing, a shortcut for turning on a breakpoint should you need it.

What I do when I am in a situation like yours is make an assert macro. (you can use the assert macro that visual studio provides, but I dont like it). Have your macro check the condition you want and then call DebugBreak if it fails. In the realease, or non-checked build of your application, have assert evaluate to nothing, so your code is not impacted.

A simple assert macro can look like:

#ifdef _DEBUG
#define assert(x)\
do{\
  if(!(x)){DebugBreak();}\
}while(0)
#else
#define assert(x)
#endif

and call it like:

assert(pValue != NULL && "A bad parameter was passed to the function");

You can put more code in the failure before DebugBreak (like printing out the condition that failed with #x, and/or the line/file number with ____FILE____ and ____LINE____ so you can double click on the message). You can write messages to the debug log with OutputDebugString and even check to see if a debugger is attached with IsDebuggerPresent to tailor your assert even more. I also like to use the && string format to give a bit more information on the particular assert.

There are a few things to be careful of when using assert. First, do not put any code that MUST be run in the macro, since it will be stripped in a non debug build. For the same reasons, don't put in code that has side effects. Also, you do not want to call DebugBreak() when a debugger is not attached because it essentially throws an exception, which if not caught, will terminate the application.

一身仙ぐ女味 2024-08-15 10:15:22
  1. 尝试在你的
    代码来测试性能。 EG

    秒表 st = new Stopwatch();
    st.Start();
    如果(我的情况)
    {
      st.Stop();
      调试器.Break();
    }
    

    不,不完全相同,但足够接近。

  2. 否 - 禁用的断点不是
    存在于正在执行的程序中。
    它只是存储在 VS 元数据中
    为了您的方便。

  1. Try putting the breakpoint in your
    code to test the performance. E.G.

    Stopwatch st = new Stopwatch();
    st.Start();
    if(my condition)
    {
      st.Stop();
      Debugger.Break();
    }
    

    No, not exactly the same but close enough.

  2. No - a disabled breakpoint is not
    present in the executing program.
    It is just stored in the VS metadata
    for your convenience.

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