Juce demo / lib performs slower with a debugger attached


#1

Both in my application, and in the Juce demo, the performance of Juce is decreased if a debugger is attached. This is for a Release build (full optimization). This happens with both the Intel C++ compiler and the MSVC compiler.

Juce Demo draw time reports 1.09 ms when running with a debugger attached. When I run the Juce Demo stand-alone from Explorer. the draw time drops to 0.79ms.

In my own app things are far worse, when I resize my main window, and it was launched from the debugger, it looks painfully slow. But when I run standalone, it is actually fairly fast (now that I compiled with Intel C++).

Nothing is written to the Output or Debug windows.

Any ideas why this would be? It’s kind of annoying…


#2

yes of cause, isn’t it the normal behavior? even if you have no debug symbols, the debugger does certain checks…


#3

yes of cause, isn’t it the normal behavior? even if you have no debug symbols, the debugger does certain checks…[/quote]

Oh yeah like what? I can’t think of anything. This is a Release build remember.


#4

inspecting variables/registers, checking for memory corruptions, range checks etc… you can debug a release build too…


#5

All of that is turned off, and the Release build isn’t using the debug heap. But let me re-check it just to be sure :slight_smile:


#6

Yep just like I thought, there are no run time checks or debug heap active in the release build. This is still a mystery.

A debugger doesn’t do anything until it gets an interrupt / exception for a breakpoint or memory watchpoint. Even if I had the runtime checking turned on, that gets compiled into the app and is not provided by the debugger.

It remains an open question why this thing is running slower with a debugger attached.


#7

yes, even if you turned all of, the debugger will produce an overhead, because it still debug, even you debugging a release build
a “debug”-build and a debugger are two different things


#8

No, there should be no overhead until a breakpoint is reached. These are implemented through exceptions.


#9

yes in theory, but if you debug there is second process in the background, which use has different tasks like checking for debug-output etc. (even if there is nothing)


#10

Under Windows at least, there is no “checking” (polling) for debug output. Sending strings to the debugger is done through a Win32 API call, which debuggers are given hooks for. If there is no debug output, there is no impact on the user application.


#11

or it does something like this ( from process-explorer )

ntdll.dll!KiFastSystemCallRet
kernel32.dll!WaitForDebugEvent+0x21
NatDbgDE.dll+0x1808
NatDbgDE.dll+0x1863
NatDbgDE.dll+0x1629
kernel32.dll!BaseThreadInitThunk+0x12
ntdll.dll!RtlInitializeExceptionChain+0x63
ntdll.dll!RtlInitializeExceptionChain+0x36


#12

and remember you always debugging all other system/libs stuff too, not only your own code


#13

You should read the code again from both side:

  • isRunningUnderDebugger returns differently if you are under a debugger or not
  • thread name uses a Windows’s specific exception for this
  • A debugger has to serialize its data, even if there is no breakpoint set up. This is because when a exception happens, the program is not in a determined state (for example, a stack overflow could prevent the debugger’s remote thread in your software to work). So the debugger actually inject its own thread in your program, hooking some functions like CreateThread / WaitForSingleObject etc… That way, when you click on “break” button, the process can actually be stopped even if it was in a middle of a WaitForSingleObject(INFINITE). I’m not speaking about the list of the instruction code that the debugger must remember for all the breakpoints (a breakpoint is just a INT 3 inserted inplace of the binary code, the debugger must restore this before actually continuing).
    Also a debugger must handle SEH on top of the application (as it must clean itself up on exception), and this is a per-thread operation too.

I’ve done a debugger-like code here, but instead it was used to mathematically prove thread safety. The basic system is the same as for a debugger.


#14

[quote=“X-Ryl669”]You should read the code again from both side:

  • isRunningUnderDebugger returns differently if you are under a debugger or not
  • thread name uses a Windows’s specific exception for this
  • A debugger has to serialize its data, even if there is no breakpoint set up. This is because when a exception happens, the program is not in a determined state (for example, a stack overflow could prevent the debugger’s remote thread in your software to work). So the debugger actually inject its own thread in your program, hooking some functions like CreateThread / WaitForSingleObject etc… That way, when you click on “break” button, the process can actually be stopped even if it was in a middle of a WaitForSingleObject(INFINITE). I’m not speaking about the list of the instruction code that the debugger must remember for all the breakpoints (a breakpoint is just a INT 3 inserted inplace of the binary code, the debugger must restore this before actually continuing).
    Also a debugger must handle SEH on top of the application (as it must clean itself up on exception), and this is a per-thread operation too.

I’ve done a debugger-like code here, but instead it was used to mathematically prove thread safety. The basic system is the same as for a debugger.[/quote]

Impressive ! :shock:


#15

This may apply too:

“Running under a Microsoft debugger (windbg, kd, cdb, Visual Studio Debugger) by default forces Windows to use the debug heap instead of the default heap. On Windows 2000 and above, the default heap is the Low Fragmentation Heap, which is insanely good compared to the debug heap. You can query the kind of heap you are using with HeapQueryInformation.”

http://efreedom.com/Question/1-1060337/STL-Code-Run-Slowly-Debugger-IDE-Attached


#16

[size=150]THANK YOU[/size]

This was the right answer, cpr.

I added “_NO_DEBUG_HEAP=1” to Project Properties->Configuration Properties->Debugging->Environment for the Release target of my application executable, and voila, the speed discrepancies vanished.

Even after 15 years of working with Visual Studio it seems there is always something new to learn.

So, just having a debugger attached DOES NOT slow down the application due to hooks, breakpoints, and what not. It was the behavior of the runtime debug heap being used even for Release mode.


#17

yay! :slight_smile:


#18

Upon consideration of why and how this change improves the performance of a Release build of a Juce application, it seems that this highlights one obvious optimization: a reduction of the number of calls to new/delete/malloc/free in the rendering pipeline.


#19

The debug heap is not supposed to be enabled for release build (at least it’s not the case here). How come you’ve this switched on ? Did you did this manually ?


#20

Different heap. There’s two Debug heaps. The one that comes with the C runtime, and one built into the Windows system. The one built into the Windows system is not quite as heavy. But stll slower.