When sampling profiling on Windows 8 or Server 2012, nothing looks different in Visual Studio 2012, but the entire insides of the profiling collector is completely changed. With the profiler now based on Event Tracing for Windows (ETW) everything is spiffy but PDB files are more important than ever. While I’m sure you are all using the Symbol Servers and have all symbols for the code you build, what about the binaries you didn’t build and was built on the server/user’s machine?
If you’re installing binaries in the Global Assembly Cache or running Native Generation (NGEN) to pre-JIT your binaries, that code generation is done on each machine so each machine has a unique copy of the binary. When profiling, you need the PDB files for those unique binaries to see the JIT’d methods show up in the sampling profiling. You’re probably thinking you are safe that since you are not putting anything in the GAC you can stop reading now. Sadly you have to keep reading because the .NET Framework itself is NGEN’d on each install so if you want to see where your calls into the .NET Framework are eating your time, you need to get those PDBs from that machine.
Fortunately, it’s relatively easy to generate the PDB file for an individual computer after the binary was pre-JITTED by running NGEN.EXE again. Andrew Hall from the profiler team shows you exactly what you need to do here. I strongly suggest you read Andrew’s blog entry before continuing so the rest of what I’m talking about makes sense.
As Andrew points out, you can run NGEN.EXE to create the necessary PDB files, but you need to manually hunt down super-secret directory names for each individual DLL you need. That’s a whole bunch of manual steps that are screaming to be automated so that’s exactly what I did for you. You can grab the code at my ongoing WintellectPowerShell module up on Wintellect’s Code Page on GitHub.
My Add-NgenPdbs cmdlet will enumerate the GAC on a machine and produce the required PDB files for in one step. If you’re sampling on your Windows 8 or Server 2012 development machine, and you have the Symbol Server already set up, running Add-NgenPdbs will put all the appropriate PDB files into your symbol cache so the profiler will find them automatically.
If you are running the command line profiler on a different machine, run Add-NgenPdbs with the –CacheDirectory switch specifying an output directory. That will put all that machine’s PDB files into the directory and you’ll copy the paths onto your development machine’s symbol cache. Note that if your symbol cache is C:\Symbols\Public, Visual Studio will look for the symbols in C:\Symbols\Public\MicrosoftPublicSymbols so that’s where you would copy the directories. As I’ve been sampling profiling on various machines I’ve just gotten into the habit of always running Add-NgenPdbs before any sampling takes place because you’re going to need those PDBs. As you would guess, if you put a .NET Framework hot fix or service pack on the machine, you’ll need to rerun Add-NgenPdbs.
By default Add-NgenPdbs only does the .NET Framework NGEN’d binaries because those alone take up at least 150MB. If you need other files, specify the –DoAllGACFiles and Add-NgenPdbs will process all files on the machine’s GAC but that can chew up a lot of disk space quickly. In my sampling profiling I just needed the .NET Framework PDB files so I made that easy. Once thing I noticed is that there are a few files, mainly from SQL Server that NGEN.EXE can’t produce the PDB files so I’ll report those as errors.
If you’d like Add-NgenPdbs to handle individual binaries or match wildcards, please feel free to create a pull request. If you have ideas for any other common developer automation, feel free to request that on the WintellectPowerShell repository or send me an email at john@<this company>.com.