You can make your Visual Studio experience faster.


Often you write some code in Visual Studio, hit F5 to test the code. Repeat.


Here’s a simple way to make this experience faster. (works with managed, native, mixed code).


When a process is started from the debugger, it is started with some special DEBUG flags which tell the entire process to use the Debug heap, which is quite a bit slower than the non-Debug heap.


If you start the process without the debugger (Ctrl-F5 from VS or from Explorer, Start Menu, etc), then Attach the debugger after the process has started, then those flags are not present.


Here’s proof.


Start Visual Studio


We’ll need to set symbols once:

Tools->Options->Debugging->Symbols->Symbol File Locations. Add a single entry:


Click the checkbox: Search the above locations only when symbols are loaded manually (to make symbol loads faster)


Cache the symbols locally (type in something like C:\Symbols)


Choose File->New Project->VB  console application. (similarly with C#)


On the toolbar, make sure to select Release build (so you don’t think this is just with Debug bits)


Enable Project->Properties->Debug->Enable Unmanaged Code Debugging.


Add a single line of code to your fancy program:



Or in C# if you want the VB MsgBox function: add a references to Microsoft.VisualBasic.dll




Or you can add a reference to System.Windows.Forms.dll (both C# and VB)




Hit F5 to start the process under the debugger and see the MsgBox.


Without terminating your fancy program, switch back to VS and choose Debug->Windows->Modules


Right click on NTDLL.dll, load symbols. Hit Ctrl-B to bring up the Breakpoint dialog, paste in “_RtlDebugFreeHeap@12” and make sure the Language says C++.


The breakpoint dialog (Debug->Windows->Breakpoints) will show the Breakpoint with a solid red dot when the breakpoint is resolved. This Breakpoint is in the debug heap code.


Now dismiss the MsgBox


The debugger breaks. Here’s a sample call stack:

                ntdll.dll!_RtlpInsertFreeBlock@12()  + 0x3299 bytes       

                ntdll.dll!_RtlpDeCommitFreeBlock@16()  + 0x41 bytes  

                ntdll.dll!@RtlpFreeHeap@16()  + 0x2bb9 bytes 

                ntdll.dll!_RtlFreeHeap@12()  + 0x2e49 bytes      

                ntdll.dll!_RtlDebugFreeHeap@12()  + 0x1f8 bytes            

                ntdll.dll!@RtlpFreeHeap@16()  + 0x13cdd bytes               

>             ntdll.dll!_RtlFreeHeap@12()  + 0x2e49 bytes      

                kernel32.dll!_HeapFree@12()  + 0x14 bytes       


Now stop debugging, launch the process again, this time without the debugger (Ctrl-F5).


With the MsgBox showing, attach the debugger (Tools->Attach to Process->navigate to ConsoleApplication) in Native mode: select Native in Attach To: Select Code Type.


Repeat loading symbols, and setting the breakpoint. Now when you dismiss the MsgBox, the breakpoint doesn’t get hit because the Debug heap isn’t used.


So, how do I make my experience faster? One way is to hit Ctrl-F5, then Attach (if your fingers are fast).


However, there’s a simpler way:

Control->Panel->System Properties->Advanced System Settings->Environment Variables->System Variables.

Add a new Variable called “_NO_DEBUG_HEAP” with a value of “1”


Now repeat the steps above and you’ll not hit that breakpoint.


Beware of taking performance measurements when you start the process under the debugger. For example, I sometimes use OutputDebugString to output some times of some crude measurements. When running under the debugger, the performance of CPU bound code that doesn’t load modules or have breakpoints is pretty much the same as without a debugger, *IF* you don’t use the debug heap!


Of course, if you’re debugging heap problems, you may not want to set the environment variable.


See also:


Dynamically attaching a debugger