views:

148

answers:

2
+11  Q: 

C# Debug vs Release

How much performance gain (if any) can a windows service gain between a debug build and release build and why?

+6  A: 

For managed code, unless you have a lot of stuff conditionally compiled in for DEBUG builds there should be little difference - the IL should be pretty much the same. The Jitter generates differently when run under the debugger or not - the compilation to IL isn't affected much.

There are some things the /optimize does when compiling to IL, but they aren't particularly aggressive. And some of those IL optimizations will probably be handled by the jitter optimizations, even if they aren't optimized in the IL (like the removal of nops).

See Eric Lippert's article http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx for details:

The /optimize flag does not change a huge amount of our emitting and generation logic. We try to always generate straightforward, verifiable code and then rely upon the jitter to do the heavy lifting of optimizations when it generates the real machine code. But we will do some simple optimizations with that flag set.

Read Eric's article for information about /optimize does do differently in IL generation.

Michael Burr
Good stuff ... what about security? If you ship/expose with debug information, will an inspection reveal more about your code? Even if there is negligible difference in performance, I wouldn't ship debug code unless I had to.
Edward Leno
@Edward: I'm not really advocating distributing DEBUG builds, just saying that you probably shouldn't expect a major difference in performance between DEBUG and RELEASE builds. Also, I don't think that a DEBUG build has any more detail in the assembly itself - the debug information goes in the .pdb file, which you don't need to distribute. .NET assemblies are generally pretty easily disassembled/decompiled (see the Reflector tool). If you're concerned about reverse engineering, there are obfuscation tools to help with that, but I don't really know anything about them.
Michael Burr
@Michael: Thanks ... I forgot about the .pdb having the debug info. A lot of obfuscation tools are not full-proof and potentially expensive. I always assume if someone really wants in, they will get in. I should spend more time innovating and less time protecting.
Edward Leno
@Edward: +1 for "spend more time innovating and less time protecting". The only real way to protect your code is to never let users have it, e.g., by only running it as a service. If users have your code, they *can* disassemble it. They hardly ever bother though; use a legal defense and not a technological one.
Donal Fellows
+1  A: 

Well, though the question is a duplicate, I feel that some of the better answers in the original question are at the very bottom. Personally I have seen situations where there is an appreciable difference between debug and release modes. (Example : Property performance, where there was a 2x difference between accessing properties in debug and release mode). Whether this difference would be present in an actual software(instead of benchmark like program) is debatable, but I have seen it happen in one product I worked on.

From Neil's answer on the original question, from msdn social:

It is not well documented, here's what I know. The compiler emits an instance of the System.Diagnostics.DebuggableAttribute. In the debug version, the IsJitOptimizerEnabled property is True, in the release version it is False. You can see this attribute in the assembly manifest with ildasm.exe.

The JIT compiler uses this attribute to disable optimizations that would make debugging difficult. The ones that move code around like loop-invariant hoisting. In selected cases, this can make a big difference in performance. Not usually though.

Mapping breakpoints to execution addresses is the job of the debugger. It uses the .pdb file and info generated by the JIT compiler that provides the IL instruction to code address mapping. If you would write your own debugger, you'd use ICorDebugCode::GetILToNativeMapping().

apoorv020