After a detour into Historical Debugging, it’s time to come back to return to answering questions about PDB files. Here’s a question from Justin:

Thanks for the great post once again. I was looking forward to your debugging virtual training, but unfortunately it was cancelled.

The company I work for is pushing pack against building release mode
binaries with debug information generated, one of the reasons I signed
up for the class :). They are afraid performance will be affected.


My question is what are the best command line arguments for
generating symbols in release mode? Also is there somewhere I can
reference to show that there should be no performance hits.

I’m sorry about the canceled class, but the good news is that Mastering .NET Debugging was rescheduled to July 14-15.

The executive summary answer: no, generating PDB files will have no
impact on performance whatsoever. As for references that I can point you
too, I haven’t found any on the web that answer the exact question so
let me take both .NET and native development in turn.

Recently, the always-readable Eric Lippert wrote a great post What Does the Optimize Switch Do?
where he discusses the optimizations done by the compiler and Just in
Time (JIT) compiler. (Basically, you can sum it up as the JITter does
all the real optimization work.) There’s a bit of confusion on the C#
and VB.NET compiler switches around as there are four different /debug
switches, /debug, /debug+, /debug:full, and /debug:pdb-only. I
contributed to that confusion because I thought /debug:pdb-only did
something different that was better for release builds than the other
three /debug switches.

All four switches all do the same thing in that they cause a PDB file
to be generated but why are there four switches to do the same thing?
Do Microsoft developers really love parsing slightly different command
line options? 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.

What controls whether the JITter does a debug build is the /optimize switch. Building with /optimize- will add an attribute, DebuggableAttribute, in the assembly and setting the DebuggingMode
parameter to DisableOptimizations. It doesn’t take a Rhodes Scholar to
figure out that DisableOptimizations does exactly what it says.

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. Read the Visual Studio documentation to see how where to set those switches in the different types of projects.

It’s easy to prove these are the optimal switches. Taking my Paraffin program, I compiled one build with /optimize+ and /debug, and another with just /optimize+.

which is the same as /debug+ and /debug, and the other with /optimize+ /debug:pdbonly to show the differences, which is the root of how we got it wrong. After compiling, I used ILDASM with the following command line to get the raw information from the binaries

ILDASM /out=Paraffin.IL Paraffin.exe

Using a diff tool you’ll see that the IL itself is identical between both builds. The main difference will be in the DebuggableAttribute declaration for the assembly. When built /optimize+ and a /debug switch, a DebuggingMode.IgnoreSequencePoints is passed to the DebuggableAttribute to tell the JIT compiler that it doesn’t need to load the PDB file in order to correctly JIT the IL. A value of DebuggingMode.Default is also OR’d in, but that value is ignored.

Like .NET, building PDB files has nothing to do with optimizations so have zero impact on the performance of an application. If you have a manager who in Justin’s words is “afraid performance will be affected” here’s what I tell them.  (Sadly, I’ve run into a few more managers who say that than I care to count).

That might be true on other operating systems, but not Windows. If you think they do, then why does Microsoft build every single product they ship with PDB files turned on for both debug and release builds? They wrote the compiler, they wrote the linker, and they wrote the operating system so they know exactly what the effects are. Microsoft has more people focused on performance than any other software company in the world. If there were any performance impact at all, they wouldn’t do it. Period. Performance isn’t the only thing at Microsoft, it’s everything.

Where .NET is pretty simple as there’s really only two switches, the appropriate optimization switches are dependent on many individual application factors. What I can tell you is what the switches you need to set to generate PDB files correctly in release builds.

For CL.EXE, the compiler, you need to add /Zi to have it put debugging symbols into the .OBJ file. For LINK.EXE, the linker, you need to specify three options. The first is /DEBUG, that tells the linker to generate a PDB file. However, that switch also tells the linker that this is a debug build. That’s not so good because that will affect the performance of your binary. Basically what happens when you use /DEBUG is the linker links faster because it no longer looks for individual references. If you use one function from a OBJ the linker throws the whole OBJ into the output binary so you now have a bunch of dead functions.

To tell the linker you want only the referenced functions, you need to add /OPT:REF as the second switch. The third switch is /OPT:ICF, which enabled COMDAT folding. There’s a term you don’t hear every day. Basically what this means is that when generating the binary, the linker will look for functions that have identical code and only generate one function but make multiple symbols point to the one function.

If you want to test the difference yourself on a native binary to see what affects generating PDB files will have, it’s nearly as easy as a .NET binary. Visual Studio comes with a nice little program, DUMPBIN, which can tell you more than you ever wanted to know about a Portable Executable file. Run it with /DISASM switch to get the disassembly of a binary.

Please keep those PDB related questions coming. Of course, if you have any other questions, I’ll be happy to take a crack at those also. Gee, I better draw the line: no investment or relationship questions. <grin>

最新文章

  1. jmeter(九)逻辑控制器
  2. Swift 写纯洁的TableviewCell
  3. Java线程并发控制基础知识
  4. 详细的图文教程来实现 eclipse环境下如何配置tomcat,并且把项目部署到Tomcat服务器上
  5. 【python cookbook】【字符串与文本】2.在字符串的开头或结尾处做文本匹配
  6. JNI中使用cl命令生成DLL文件
  7. NFC简介
  8. repo的小结
  9. Javaweb向服务器上传文件以及从服务器下载文件的方法
  10. FFMPEG列出DirectShow支持的设备
  11. Nginx禁止IP直接访问网站
  12. 关于JWTtoken的管理问题
  13. idea debug快捷键 快速查找类
  14. 初次接触Jenkins遇到的几个问题
  15. php 使用str_replace替换关键词(兼容字符串,一维数组,多维数组)
  16. [C#]获取指定文件夹下的所有文件名(递归)
  17. 非mapreduce生成Hfile,然后导入hbase当中
  18. 2018.11.06 NOIP训练 最大获利(profit)(01分数规划+最大权闭合子图)
  19. cos,sina,tan,cot
  20. C#内置泛型委托:Func委托

热门文章

  1. Spring Cloud Alibaba微服务一站式解决方案-开篇v2.2.1.RELEASE
  2. Codeforces 582D - Number of Binominal Coefficients(Kummer 定理+数位 dp)
  3. exit(0) exit(1) return() 3个的区别
  4. Bootstrap实战 - 瀑布流布局
  5. Tomcat类加载机制和JAVA类加载机制的比较
  6. 日常Java 2021/10/4
  7. Oracle—全局变量
  8. Android EditText软键盘显示隐藏以及“监听”
  9. Output of C++ Program | Set 5
  10. wsdl实例