Shrink my Program Database (PDB) file


PDB’s (Program Database file), PDB stands for Program Database, a proprietary file format (developed by Microsoft) for storing debugging information about a program (or, commonly, binaries such as a DLL or EXE). PDB files commonly have a .pdb extension. A PDB file is typically created from source files during compilation although other variants exist (also created by the linker when /Z7 is used). It stores a list of all symbols in a module with their addresses and possibly the name of the file and the line on which the symbol was declared. This symbol information is not stored in the module itself, because it takes up a lot of space.

This blog in particular goes over a few ways to shrink your PDB size, so let’s get started. For demonstrating the effectiveness of these ways I have used the popular BingMaps (bingmaps.dll) windows store application.

#1. The /OPT:REF and /OPT:ICF effect

Linker has a good view of all the modules that will be linked together, so linker is in a good position to optimize away unused global data and unreferenced functions. The linker however manipulates on a OBJ section level, so if the unreferenced data/functions are mixed with other data or functions in a section, linker won’t be able to extract it out and remove it. In order to equip the linker to remove unused global data and functions, we need to put each global data or function in a separate section, and we call these sections “COMDATs“. (The COMDAT construction is enabled by the /Gy and /Gw compiler flags). COMDATs and usage of these flags /OPT: REF and /OPT: ICF enable (here’s how to do this) linker optimizations. /OPT:REF eliminates functions and data that are never referenced and /OPT:ICF performs identical COMDAT folding. The two together form a strong force and the result is a smaller binary and hence also a smaller PDB.

Please note, enabling linker optimizations today disables incremental linking however.

#2. The /d2Zi+ effect

The usage of cryptic but undocumented switch is common especially for debugging optimized code. In particular, it provides more debug information for locals and inline behaviour. The side-effect of using this flag for all scenarios however results in PDB size growth. The exact specifics of the size increase are application dependent.

#3. Compress the PDB using /PDBCompress

For clean link scenarios /PDBCOMPRESS instructs the linker to open the target PDB file in a mode that will lead to the operating system compressing the file content automatically as debug records are being written into the PDB file.  This will result in a smaller PDB.  This switch won’t have any impact if the operating system’s file system does not support compression, or the linker is asked to update an existing PDB file to which compression by OS’ file system hasn’t been applied.

Figure 1: Effect of /pdbcompress on BingMaps PDB

Please note, the impact of this compression can be observed by looking at the ‘size on disk’. If looking in windows explorer, compressed PDB’s will light up in blue. 

#4. Incremental Update to PDB’s

During incremental linking, we don’t remove unreferenced type records (which is same as in full linking), also for public and global records, we don’t remove obsolete ones (which is for throughput purpose)..  Over extensive use which is numerous rebuild/relink iterations the size of the PDB grows. We recommend a clean link (build) when possible for reducing the size of PDB’s.

Sum it all up

To conclude, attached below is the result of enabling the above techniques on the popular BingMaps Windows Store application.

As you can see there are some clear wins with the methodologies described. Please note the vanilla build setting here is an optimized (/O2) build with /Zi (Program Database) enabled.

Reach out to us if you have questions, concerns or feature requests w.r.t the linker and PDB’s.

Additionally, if you would like us to blog about some other compiler technology or compiler optimization please let us know we are always interested in learning from your feedback.