126

In Visual Studio for a C# project, if you go to Project Properties > Build > Advanced > Debug Info you have three options: none, full, or pdb-only.

Which setting is the most appropriate for a release build?


So, what are the differences between full and pdb-only?

If I use full will there be performance ramifications? If I use pdb-only will it be harder to debug production issues?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
RationalGeek
  • 9,425
  • 11
  • 62
  • 90
  • The pdb-only or none, always for release builds. – leppie Oct 10 '11 at 13:35
  • 15
    @leppie Thanks but I'm looking for some justification of that position. – RationalGeek Oct 10 '11 at 13:47
  • Related question: http://stackoverflow.com/questions/1270986/do-pdbs-slow-down-a-release-application – janv8000 Mar 10 '15 at 07:17
  • That's great if there's no performance impact. What about memory impact? If I create an instance of StackTrace and request file information, it has to come from the pdb symbol data. Are all symbols loaded into memory on application start? What is the approximate memory use of this? (e.g. percentage overhead relative to code size.) – yoyo Apr 16 '15 at 17:40

4 Answers4

97

I would build with pdb-only. You will not be able to attach a debugger to the released product, but if you get a crash dump, you can use Visual Studio or WinDBG to examine the stack traces and memory dumps at the time of the crash.

If you go with full rather than pdb-only, you'll get the same benefits, except that the executable can be attached directly to a debugger. You'll need to determine if this is reasonable given your product & customers.

Be sure to save the PDB files somewhere so that you can reference them when a crash report comes in. If you can set up a symbol server to store those debugging symbols, so much the better.

If you opt to build with none, you will have no recourse when there's a crash in the field. You won't be able to do any sort of after-the-fact examination of the crash, which could severely hamper your ability to track down the problem.

A note about performance:

Both John Robbins and Eric Lippert have written blog posts about the /debug flag, and they both indicate that this setting has zero performance impact. There is a separate /optimize flag which dictates whether the compiler should perform optimizations.

Matt Dillard
  • 14,677
  • 7
  • 51
  • 61
  • There is no mention of the fact that full will impact performance and could therefore be misleading. – Martin Jan 10 '12 at 09:59
  • 1
    Martin, are you sure that there is a performance impact when using "full"? From what I've read, the "/debug" switch has no impact on performance at all. See my recent edits for a few references. – Matt Dillard Jan 10 '12 at 20:49
  • :/ now I'm even more confused. It seems that there is no difference between the 2 flags according that flag (an article I have now read 4+ times at least I might add). therefore, although there is no mention of the performance impact (it seems rightly), you do say that doing "PDB-Only" will not allow you to attach to a released product, but if it's the same as debug full, then you should be able to. I'l remove my downvote, but can you clarify? – Martin Jan 11 '12 at 14:50
  • From what I understand, the difference between the two is related to whether you can attach to a _running_ process midstream. When "full" is specified, a debugger CAN attach to a running process. If "pdb-only" is specified, then a debugger CANNOT attach to the running process. Either setting will allow you to launch the application under a debugger, however. – Matt Dillard Jan 13 '12 at 18:28
  • 7
    @Matt, the [MSDN article on the /debug switch](http://msdn.microsoft.com/en-us/library/8cw0bt21.aspx) explicitly warns about a performance impact of using the 'full' setting: `If you use /debug:full, be aware that there is some impact on the speed and size of JIT optimized code and a small impact on code quality with /debug:full. We recommend /debug:pdbonly or no PDB for generating release code.` – Allon Guralnek Feb 16 '12 at 09:18
  • @AllonGuralnek, the MSDN documentation is wrong. John Robbins addresses this in one of his [blog post comments](http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/06/19/do-pdb-files-affect-performance.aspx#9864). – Matt Dillard Feb 16 '12 at 19:38
  • 3
    @Matt: If 'full' has no disadvantages compared to 'pdb-only', but only has advantages, why does 'pdb-only' even exist? Is there any reason to use it over 'full'? Also, you should add the correction to the MSDN article in the 'Community Content' section. – Allon Guralnek Feb 16 '12 at 19:45
  • @AllonGuralnek, that's a good question. I'll admit that I'm standing on the shoulders of others who have done this work. :-) My guess as to why one would choose "pdb-only" over "full" is simply that it might be harder for a customer to initiate a debugging session against released code. That assumes they have the symbols in the first place, though, so I'm not sure. And that's a good idea about adding this to the 'Community Content' section of the MSDN article; I'll do that. – Matt Dillard Feb 16 '12 at 19:53
  • 10
    @AllonGuralnek quote from the linked John Robbins article: *The real reason: history. Back in .NET 1.0 there were differences, but in .NET 2.0 there isn't. It looks like .NET 4.0 will follow the same pattern. After double-checking with the CLR Debugging Team, there is no difference at all.* – bentayloruk May 10 '13 at 08:34
  • Following MSDN article talks about debuggable attribute which gets inserted into MSIL code for linking it with symbols present in pdb files. Hope this helps! http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx – RBT Jan 13 '15 at 02:59
  • 5
    This isn't true. You can build with pdb-only and still attach a debugger. I just did it just to be sure. – Mark Aug 28 '15 at 18:49
  • 2
    "I would build with pdb-only. You will not be able to attach a debugger to the released product" What's your source of information here? As both @Mark and I have noted, this does not seem to be correct. – MEMark Nov 03 '15 at 15:16
  • @MEMark, my source is the MSDN article on the /debug flag, https://msdn.microsoft.com/en-us/library/8cw0bt21.aspx. That documentation states, "Specifying pdbonly allows source code debugging when the program is started in the debugger but will only display assembler when the running program is attached to the debugger." The documentation was wrong about the effect of /debug:full on performance, so it could well be wrong about this, too. – Matt Dillard Nov 03 '15 at 15:24
  • @MattDillard Thank you for replying. I can verify that you have correctly reproduced the information given there. However, this contradicts my experience, and this answer also suggests that the MSDN page is seriously out-of-date. http://stackoverflow.com/a/28980070/268091 – MEMark Nov 03 '15 at 15:30
73

WARNING MSDN documentation for /debug switch (In Visual Studio it is Debug Info) seems to be out-of-date! This is what it has which is incorrect

If you use /debug:full, be aware that there is some impact on the speed and size of JIT optimized code and a small impact on code quality with /debug:full. We recommend /debug:pdbonly or no PDB for generating release code.

One difference between /debug:pdbonly and /debug:full is that with /debug:full the compiler emits a DebuggableAttribute, which is used to tell the JIT compiler that debug information is available.

Then, what is true now?

  1. Pdb-only – Prior to .NET 2.0, it helped to investigate the crash dumps from released product (customer machines). But it didn't let attaching the debugger. This is not the case from .NET 2.0. It is exactly same as Full.
  2. Full – This helps us to investigate crash dumps, and also allows us to attach debugger to release build. But unlike MSDN mentions, it doesn't impact the performance (since .NET 2.0). It does exactly same as Pdb-only.

If they are exactly same, why do we have these options? John Robbins (windows debugging god) found out these are there for historical reasons.

Back in .NET 1.0 there were differences, but in .NET 2.0 there isn’t. It looks like .NET 4.0 will follow the same pattern. After double-checking with the CLR Debugging Team, there is no difference at all.

What controls whether the JITter does a debug build is the /optimize switch. <…>

The bottom line is that you want to build your release builds with /optimize+ and any of the /debug switches so you can debug with source code.

then he goes on to prove it.

Now the optimization is part of a separate switch /optimize (in visual studio it is called Optimize code).

In short, irrespective of DebugInfo setting pdb-only or full, we will have same results. The recommendation is to avoid None since it would deprive you of being able to analyze the crash dumps from released product or attaching debugger.

rpattabi
  • 9,984
  • 5
  • 45
  • 53
  • 3
    Fantastic answer! My own investigations (comparing generated files) show the same results. – MEMark Nov 03 '15 at 15:27
  • @rpattabi Can you specify the reference that pdbonly and full are the same? It's 2019 and the documentation still indicates that they are different and full will have performance degradation. And VS2019 creates project with `Release` configuration's debugtype by default set to `pdbonly`. – joe Sep 16 '19 at 11:57
  • @joe There is a discussion at the bottom of the MSDN documentation https://msdn.microsoft.com/en-us/library/8cw0bt21.aspx . Take a look at it. One contributor pointed to https://github.com/dotnet/roslyn/blob/master/docs/compilers/CSharp/CommandLine.md for up-to-date information where pdbonly and full are mentioned as same. (FYI. I don't use windows or VS anymore. So I have not been following what is happening there. But as I reviewed, the information in my answer is still relevant and MSDN doc is still incorrect.) – rpattabi Sep 24 '19 at 05:02
16

You'll want PDB only, but you won't want to give the PDB files to users. Having them for yourself though, alongside your binaries, gives you the ability to load crash dumps into a debugger like WinDbg and see where your program actually failed. This can be rather useful when your code is crashing on a machine you don't have access to.

Full debug adds the [Debuggable] attribute to your code. This has a huge impact on speed. For example, some loop optimizations may be disabled to make single stepping easier. In addition, it has a small effect on the JIT process, as it turns on tracking.

CarComp
  • 1,929
  • 1
  • 21
  • 47
blowdart
  • 55,577
  • 12
  • 114
  • 149
  • Makes sense. I don't really distribute DLLs to the users anyways - it is an ASP.NET app. But can you enhance your answer and justify *why* you should go with "pdb-only" vs. "full"? Is it a performance issue? – RationalGeek Oct 10 '11 at 13:46
  • @jkohlhepp: I would like to add though that debugging release builds is a bit tricky since you will lose some information (due to JIT). Almost always, you won't be able to see the values of method arguments. To workaround this, you can temporarily disable JIT optimization using [this](http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx). – Ilian Oct 10 '11 at 13:59
  • Thanks blowdart, and thanks Ilian Pinzon for the additional info. I know you can't get perfect debugging with release code but having the PDBs is better than nothing. – RationalGeek Oct 10 '11 at 14:44
  • Using the "full" setting does _not_ have a performance impact. It simply allows a debugger to be attached to a running process. – Matt Dillard Feb 16 '12 at 19:42
  • 1
    Good question on MSDN Matt, http://msdn.microsoft.com/en-us/library/8cw0bt21, waiting for the answer myself. – Luke Hutton Feb 24 '12 at 20:22
  • @blowdart loop optimizations are done by optimize switch and not debug switch. Also DebuggableAttribute is added into meta data for both debug:full or pdbonly switches. It represents a union of bitwise DebuggingModes flag which has following values: IgnoreSymbolStoreSequencePoints,EnableEditAndContinue,DisableOptimizations Value of DebuggableAttribute flag for all 4 combinations: full & optimize-(01 00 07 01 00 00 00 00) full & optimize+(01 00 03 00 00 00 00 00) pdb-only & optimize+(01 00 02 00 00 00 00 00) pdb-only & optimize-(01 00 02 01 00 00 00 00) – RBT Jan 15 '15 at 01:03
5

I'm in the process of writing a unhandled exception handler and the stack trace includes the line number when pdb-only is used, otherwise I just get the name of the Sub/Function when I choose None.

If I don't distribute the .pdb I don't get the line number in the stack trace even with the pdb-only build.

So, I'm distributing (XCOPY deploy on a LAN) the pdb along with the exe from my VB app.

rheitzman
  • 2,247
  • 3
  • 20
  • 36