This post is part of my PDC09 Conference Notes series. These are my raw notes taken while watching the various session videos from PDC09. Refer to my original post for some conventions I tried to use.
PDC Session Link: Advanced WPF Application Performance Tuning and Analysis
This presentation was how you can analyze and tune your WPF applications in 4 key areas: Memory Usage, Cold Startup Time, Warm Startup Time, and Runtime. There were several tools used through out the presentation, and the demos were very well done. I would recommend watching this session to get a better feel for the concepts. The sample application used for the session is called Fishbowl, and is a WPF application that lets you work with Facebook in new ways.
Introduction
- Measure early and measure often
- Be sure to test on older hardware
- Grab low hanging fruit
- Understand perceived performance (i.e. keep the UI responsive during long running requests)
- Trade Offs
- CPU vs. Memory vs. Disk IO
- Within your application, you may have to pick and choose which features are faster then others
Memory Usage
- 150MB of memory was deemed as high for an application like Fishbowl
- I found this to be very surprising given how many seemingly simple WPF apps I have seen using over 200mb of memory at startup. Is memory cheap these days? Yes, unless you count limited memory on Netbooks, older computers, and virtual machines.
- Process Explorer to view overall memory usage
- Sys-internals VMap to view detailed memory usage by process
- Image: .exe, .dll, etc
- Heap: Pure managed applications should have lower native heap then managed heap. You will always have some native heap, as some CLR stuff uses native memory, like the render thread. Images (pictures) are also stored in the native heap and are one source of high native heap usage.
- Managed:
- The cause of the high memory usage was the use of 114 images for the startup animation.
- # of images * width in pixles * hieght in pixles * 4 (32 bit color) = memory usage
- 114 * 272 * 294 * 4 = 34.7MB
- The actual cause turned out to be that the start view was not being disposed after it was finished, so the images remained in memory.
- SaciTech Memory Profiler on memProfiler.com
- Costs money
- WPF perf team uses this tool internally
- Lets you do snapshots so you can compare memory usage over time
- You can drill down by object type, as well as what is holding onto the reference for a particular object.
- Element count (virtualization) is another pain point
Cold Start
- Cold start is impacting most by Disk IO
- Windows Performance Tool Kit or Windows SDK?
- xperf command line tool (there is a PDC session on xpef and ETW)
- Event Tracing for windows (ETW): Add ETW statements to your app and profile with xperf
- Demo showed a batch file to start up xperf
- Look for for highest number of reads
- Remove unneeded dll references
- System.Windows.Forms and System.Windows.Drawing shouldn’t be needed in pure WPF application
- If you are using only one or two methods from a dll, you could merge it into your application
- You can use Scitech Mem Profiler to see how many types for dll to see you can eliminate or merge
- If you are using a managed API that is dealing with win32 api’s, you could add p/Inovke’s to your code to eliminate an extra dll.
- Be sure to test in release mode with no debuggers attached
- You can use NGen to speed up cold start, but it might slow down warm start
Warm Start
- Warm Start is CPU bound, so you will see high CPU usage. There should also be lower disk IO then cold start.
- If you see low CPU usage, there might be something blocking, like network access (using xperf again)
- CPU Profiler
- Comes with Team Suite
- WPF Perf
- Part of Windows Performance tool kit
- Check item count, is virtualization enabled. Sometimes virtualization can’t be used, like when list element height is dynamic, which would screw up the scroll bar
Runtime
- More WPF Perf usage
- Trouble shoot jerky animations
- Layout vs. Rendering
- Pererator Tool:
- Review hardware IRT’s. In the example, 20 hardware IRTs was too high.
- Problem was traced to drop shadow animation. Solution was to create two elements, one with and one without drop shadow, then toggle visibility
- Other stuff
- Don’t block on the UI thread
- Virtualization when needed
- Freeze your freezables
- No change notification call backs
- Hardware vs. Software
- use RenderCapabilities.Tier to determine when you should dial down visual effects.