views:

370

answers:

3

Working on a screen saver for my wife, http://cchearts.codeplex.com/, and while I've been able to improve FPS on lower end machines the CPU usage still seems very high.

Here's some numbers I ran from a few 5 minute sampling periods:

~60FPS 35% average CPU on Core 2 Duo T7500 @ 2.2GHz, 3GB ram, NVIDIA Quadro NVS 140M (128MB), Vista [My dev laptop]

~40FPS 50% average CPU on Pentium D @ 3.4GHz, 1.5GB ram, Standard VGA Graphics Adapter (unknown), 2003 Server [A crappy desktop]

I can understand the lower frame rate and higher CPU usage on the crappy desktop but it still seems pretty high and 35% on my dev laptop seems high as well.

I'd really like to analyze the application to get more details but I'm having issues there as well so I'm wondering if I'm doing something wrong (never profiled WPF before).

WPF Performance Suite:

Process Launch Error

Unable to attach to process: CCHearts.exe Do you want to kill it?

This error message occurs when I click cancel after attempting launch. If I don't click cancel it sits there idle, I guess waiting to attach.

Performance Explorer:

Could not launch C:\Projects2\CC.Hearts\CC.Hearts\bin\Debug (USEVISUAL)\CCHearts.exe. Previous attempt to profile the application finished unsuccessfully. Please restart the application.

Output Window from Performance:

Profiling started. Profiling process ID 5360 (CCHearts). Process ID 5360 has exited. Data written to C:\Projects2\CC.Hearts\CCHearts100608.vsp. Profiling finished. PRF0025: No data was collected. Profiling complete.

So I'm stuck wanting to improve performance but have no concrete way to determine where the bottleneck is. Have been relatively successful throwing darts at this point but I'm beyond that now :)


Summary:

Lot's of progress so far...

Performance Explorer

Problem: Wasn't working, vague error message.

Solution: Used the command line version to get a real error message that pointed me to this thread pointing out that it was a Symantec dll blocking me. Setting the following registry key fixed the problem:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysPlant]

"Start"=dword:00000004

WPF Performance Suite

Problem: Wasn't working, no error message.

Solution: Use the WPF Performance Suite designed for .NET 4 from the Windows SDK 7.1 instead of the previous version from Windows SDK 7 (I feel silly :-P)

WPF Animation

Problem: High CPU usage compared to FPS/percieved workload.

Solution: Lots ok tweaks here and there. But the HUGE improvement was Cached Composition as pointed out by Jeremiah Morrill. Check out the changesets.

A: 

You don't want to overlly optimize. The first question that needs to be answered is what are most screensavers performance?

If everything takes 50% CPU then I would not worry (I doubt that is the case). If you want to save cycles the best before just blindly throw darts make sure you really understand the 3D aspects of WPF.

Here is the best place to start

Maximize WPF 3D Performance

David Basarab
That's a good first question and one I'm not sure how to quantify. On the "crappy desktop" mentioned above the secondary cooling kicks in when my screen saver is running. This doesn't occur with any of the stock Windows screen savers or a (*MUCH* less animated) WinForms screen saver I wrote earlier.
Cory Charlton
A: 

I noticed a similar steady high CPU usage (~95%) on a Celeron 1.1Ghz, but I never noticed any performance degradation as a result of turning on the animation. I never quantified the FPS, though I suspect it was pretty low. My impression is that WPF follows an opportunistic resource utilization strategy, taking what it can to get the best quality it can muster, but not so much that it interferes with other processing. If you load up the CPU with other tasks, I suspect the CPU usage associated with the graphics will drop accordingly.

Dan Bryant
+3  A: 

I downloaded your code and saw ~20-28% CPU usage on my quad-core 2.6ghz. By adding cached composition, I was able to get it down to ~6-8% CPU.

I compiled using "DEBUG", not "DEBUG(USEVISUAL)" and in Heart.xaml I added the BitmapCache to the Path:

Path CacheMode="BitmapCache" ...

Jeremiah Morrill
Very interesting. I'll have to look into this. I ditched the Heart.xaml for the DrawingVisual because it was supposedly lighter weight but the seems to be spending a lot of time rendering (~25%). Will definitely have to check this out. Thanks for much for taking the time to look into this.
Cory Charlton
No problem. I'm unsure how to get BitmapCache working on your DrawingVisual as CacheMode=new BitmapCache() doesn't seem to have an effect. I'd check up on WPF's cached composition features as they are a huge performance boost.
Jeremiah Morrill
I couldn't get the `CacheMode` to work on the `DrawingVisual` but the performance difference is so huge that I can stick w/ the `Canvas`+`Path` `UserControl` for now. Maybe try to use the `DrawingVisual` with a `Shape` derived custom control in the future to trim it down further.
Cory Charlton
I forgot to mention that you are the man :-). Thanks again for pointing me towards Cached Composition. http://cchearts.codeplex.com/SourceControl/changeset/changes/67452
Cory Charlton
Here we go... Hosted my `DrawingVisual` in a `FrameworkElement` and then I can set the `CacheMode` on the `FrameworkElement` and I have a "lightweight" cached `DrawingVisual`. Thanks again for pointing me in the right direction.
Cory Charlton