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

时间:2009-10-19 15:50:33

标签: .net visual-studio debugging breakpoints conditional-breakpoint

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

我假设未执行的代码路径中的断点没有运行时影响。

所以我的问题有两个:

  1. 是否有任何资源可以量化与条件断点相关的成本,如果有,可以采取哪些措施来降低运行时评估成本?
  2. 是否有与“禁用”断点相关的费用?禁用,我的意思是VS在带有空心圆圈的排水沟中显示断点标记。
  3. 当然,如果我上面提到的任何事情没有意义,那么请指出我正确的方向。

5 个答案:

答案 0 :(得分:5)

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

但是我可以在调试窗口eval中列出一些已知较慢的东西

  • 函数调用:它们是你能做的最慢的事情,因为函数调用需要重新启动调试对象进程才能在进程中发生函数
  • 字符串比较:在引擎盖下这些回到func evals

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

答案 1 :(得分:2)

要注意的一件事(我学到了很多困难)是确保在将变量与值进行比较而不是单个=

时输入==

断点编辑器不会警告您,但在评估断点时,变量会被更改!花了一些时间用那个调试我的代码!

另外,如果我真的需要条件断点来bebug代码;我将条件添加到代码中,然后添加类似字符串stop =“here”;并在那里放一个正常的断点 - 我发现代码运行得更快。

答案 2 :(得分:0)

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

禁用的断点应该会对事物产生影响,它们只会掩盖IDE中的一些内存和GUI资源。

答案 3 :(得分:0)

  1. 尝试将断点放入您的 用于测试性能的代码。 E.G。

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

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

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

答案 4 :(得分:0)

我也注意到条件断点很昂贵,并得出与你相同的结论。我无法想象任何原因,一个禁用的断点会导致任何减速,因为我希望它只是一个编辑器的东西,如果你需要它是一个打开断点的快捷方式。

当我处于像你这样的情况时,我做的是做一个断言宏。 (你可以使用visual studio提供的assert宏,但我不喜欢它)。让宏检查您想要的条件,然后如果失败则调用DebugBreak。在应用程序的重新发布或未经检查的构建中,断言评估为空,因此您的代码不会受到影响。

一个简单的断言宏可以看起来像:

#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(),因为它实际上会抛出异常,如果没有捕获,将终止该应用程序。