Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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.

  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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top