Toward the end of my next-to-last post I suggested using the command-line to control profiling. I've been experimenting with this functionality and wanted to post what I've learned.
First, IanWho’s blog is a pretty amazing source of VSTS Profiler info. Here is his post on command-line profiling. The instructions he gives in that post should be used for startup-time profiling.
However, when measuring actions after startup, slightly different steps are needed to factor out startup time. Below are the steps I’ve been using for measuring post-startup actions:
Step-by-Step: Profiling WPF from the Command-Line
1. Setup before the app has started.
Doing this step before the app launches is very important! If you don't, managed code won't be profiled and you'll get an error similiar to this:
Warning VSP2321 : Managed code could not be profiled. Use VSPerfCLREnv.cmd to set the environment for managed code profiling
set PATH=%PATH%;"C:\Program Files\Microsoft Visual Studio 8\Team Tools\Performance Tools"
If you don’t do this, the /attach command in Step 2 won’t work.
vsperfcmd /start:SAMPLE /output:MyOutput.vsp
These commands will initialize your environmental variables, and warm-up the profiler before profiling is started. The last command will suspend profiling until you are ready to start profiling.
2. Profiling your application.
There are 2 ways to start profiling the application -- attaching to a running application, or launching the application.
Launching the application directly (to measure startup costs)
Sometimes, profiling can be very ... challenging (to your sanity). Learn this next lesson from me and save your juice for other problems. Always attach to an application instead of launching it directly, -unless- your optimizing for startup time specifically. If you don't your profile will contain both startup costs and your post-startup action, and you won't have a clue as to which is which . If your interested in optimizing both startup time and some post-startup action , then use 2 seperate profiles.
To measure startup time, use the follow to commands:
Use /globalon before launching the app so all of the startup costs are captured by the profiler.
Attaching to an application (to measure anything after startup)
First, launch the application FROM THE COMMAND LINE (the same one you used vsperfclrenv on). Otherwise the environmental variables set in Step 1 won't be picked up, and you'll get that same error:
Run these commands to measure post-startup costs:
This starts profiling & attaches the profiler to your already-running application. We use /globalon after /attach so that any costs incurred during /attach aren't included in the profile.
3. Perform the action you want to profile
4. Stop profiling
First, we turn off profiling to ensure only the interesting action was profiled, and not shutdown.
The /shutdown switch waits for the app to exit, so kill the app before attempting shutdown. You can also close it using the UI or Alt+F4.
End profiling. After this step, the .VSP log specified to the /output parameter will be generated.
5. Pack symbols
If your viewing the .VSP soley on the machine you used to gather the profile on, this step is optional. Otherwise, make sure to pack symbols before moving the .VSP to another machine.
xcopy /E "C:\Documents and Settings\timothyc\My Documents\Visual Studio 2005\Projects\MyTest\MyTest\bin\Release\*.PDB" .
Copy all of the symbols for your project to the local directory. I've found symbol packing to work -much- more consistently when symbols exist in the local directory.
set _NT_SYMBOL_PATH='WPF Symbol Server'
This command is optional for external folks who don't have access to private WPF symbol servers. A number of internal folks use this blog, so I'm mentioning it so they can make sure and maximize symbol information.
vsperfreport /summary:all /packsymbols MyOutput.VSP
This last command performs the actual symbol packing, now that symbols have been setup.
Using Batch Files
Using a batch file to start & stop profiling is really important. Not only does it minimize the performance impact of interacting with the command console, it helps ensure that results are reproducible by repeating the exact same steps in subsequent profiles. Here is the batch file I use when profiling from the command line.
REM Initialize the VSTS Profiler
call VSPerfClrEnv.cmd /sampleon
call vsperfcmd /start:SAMPLE /output:MyOutput.vsp
call vsperfcmd /globaloff
REM Initialize my app
REM Use start.exe to avoid blocking the current command console
REM Sleep for 25 seconds while my app starts up and I navigate through it
REM Start Profiling
call vsperfcmd /attach:MyTest.exe
call vsperfcmd /globalon
REM Record 20 seconds of the action
REM Stop Profiling
call vsperfcmd /shutdown