How to know why an animation stutters? - wpf

I have a few fairly simple animations (moving text around, moving ellipses etc.) and running in full screen (1920x1080 minus the task bar) the WPF Performance Suite reports a good framerate around 50 FPS throughout the animation. Dirty Rect Addition is somewhere around 300 rect/s, the SW frames are between 0 and 4 and the HW frames are between 3 and 5. Video memory usage is around 80 MB.
Problem is that the animations stutters every other half second. It is definitely not fluid :-(
My machine is a new Dell laptop XPS 15 with the GeForce GT 435 with 2GB memory. - The drivers are up to date. (The same behavior occurs on my netbook (in full screen) as well so I don't think it is hardware related.)
If I make the window smaller the stutter goes away.
The stutter occurs with the simplest of animations - even with just a couple of elements but adding more elements certainly makes it more noticeable.
How can I find out what causes this stutter?
When I think of it, I have not actually seen any WPF animations which run smoothly in full screen. Is this even possible?

Have you tried to set a lower "max frame rate" to the animation?
<Storyboard Timeline.DesiredFrameRate="10">
<!-- ....blah blah blah -->
</Storyboard>
If your animation is causing massive recalculation of child or parent elements, changing the DesiredFrameRate will have a cascading effect on the number of calculations made by the system.
Also, check out the "Remarks" section of this link. It explains why/when you should use it.
If setting a lower frame rate fixes your stuttering, then you need to consider simplifying your XAML to limit the amount of recalculation needed at every frame of your animation (limiting the number of child or parent objects resized - or affected in any way - by every frames/changes made by the animation.
You might want to also check out the "WPF Performance Suite". It is an awesome set of tools to determine what exactly is going on in your WPF app, seeing which parts of your window are being repainted and when, and the CPU usage of each of your XAML elements!
Hope this helps!

Patrick,
I have no answers. All I can do is provide some solidarity. I'm trying to animate an ItemsControl. The concept is pretty simple, really. I've got a ListView and in the ListView I have a GridView. I want the items in the GridView to to smoothly go from one row to another row as the underlying list is sorted so that, for example, a sorted list will stay sorted as the values in the list change.
I've noticed this: animation on moderately complex controls is a CPU hog. The stuttering I'm pretty sure is simply related to the CPU being maxed out (I noticed you didn't provide the CPU graph on your dump above). Keep the CPU around 50% and the animation appears smooth, above 75% and you get these stutters.
Still working on the problem, but I think it goes deeper than my code.
Don

I had a similar issue where it was stuttering, nothing really major it just looked like little stutters here and there while I ran the program. On a hunch, I shut down Google Chrome while it was running and that fixed it,the scrolling became completely smooth...
So my advice would be if you have any internet browsers open check to see if closing them out fixes the problem.

Related

Sudden fps drop during multi-touch

I have a WPF application showing a large image (1024x1024) inside a ZoomableCanvas. On top of the image, I have some 400 ellipses. I'm handling touch events by setting IsManipulationEnabled="True" and handling the ManipulationDelta event. This works perfectly when zooming slowly. But as soon as I start zooming quickly, there is a sudden frame-rate drop resulting in a very jumpy zoom. I can hear the CPU fan speeding up when this occurs. Here are some screenshots from the WPF Performance Suite at the time when the frame-rate drops:
Perforator
Visual Profiler
Software renderer kicks in?
I'm not sure how to interpret these values, but I would guess that the graphics driver is overwhelmed by the amount of graphics to render, causing the CPU to take over some of the job. When zooming using touch, the scale changes by small fractions. Maye this has something to do with it?
So far, I have tried a number of optimization tricks, but none seem to work. The only thing that seems to work is to lower the number of ellipses to around 100. That gives acceptable performance.
Certainly this is a common problem for zoomable applications. What can I do to avoid this sudden frame-rate drop?
UPDATE
I discovered that e.DeltaManipulation.Scale.X is set to 3.0.. in the ManipulationDelta event. Usually, it is around 1.01... Why this sudden jump?
UPDATE 2
This problem is definitely linked to multi-touch. As soon as I use more than one finger, there is a huge performance hit. My guess is that the touch events flood the message queue. See this and this report at Microsoft Connect. It seems the sequence Touch event -> Update bound value -> Render yields this performance problem. Obviously, this is a common problem and a solution is nowhere to be found.
WPF gurus out there, can you please show how to write a high performance multi-touch WPF application!
Well I think you've just reached the limits of WPF. The problem with WPF is that it tesselates (on CPU) vertex grafics each time it is rendered. Probably to reduce video memory usage. So you can imagine what happens when you place 600 ellipses.
If the ellipses are not resized then you could try to use BitmapCache option. In this way ellipses will be randered just once in the begining and then will be stored as textures. This will increase memory usage but should be ok I think.
If your ellipses are resized then previous technic won't work as each ellips will be rerendered when resized and and it will be even slower as this will rewrite textures (HW IRTs in perforator).
Another possibility is to design special control that will use RenderTargetBitmap to render ellipses to bitmaps and then will render it through Image control. In this way you can control when to render ellipses you could even render them in parralel threads (don't forget about STA). For example you can update ellipse bitmaps only when user interaction ends.
You can read this article about WPF rendering. I don't agree with the author who compares WPF with iOS and Android (both use mainly bitmaps compared to WPF). But it gives a good explanation about how WPF performs rendering.

WPF Performance. Wrong dirty rect calculation

I currently work in a customer assignment related to performance problems in a WPF rich client LOB application.
The problem is that the application runs very slow/sluggish. Especially data table handling (scrolling, sorting, selection) is extremely slow and leaves the application unusable.
I analyzed the system state when a single tab containing a few textboxes, comboboxes and labels is opened and left idle (waiting for user input).
These are my findings:
All the rendering is calculated on the GPU
There are no performance heavy features such as animations, bitmap effects, transparency, etc.
When the tab is idle (only the cursor is blinking in the focused textbox, the rest of the tab is static and does not even contain any data) the GPU runs up to 90%
GPU drops to 0 whenever the tab loses focus
GPU percentage directly relates to the window size. A small window brings it down to a few percent, full screen makes it go up to almost 100%
WPF Perforator tells me that WPF calculates the dirty region for the entire tab instead of only the blinking cursor
WPF Perforator reports dirty rect update rates larger than 20/sec on the idle tab and they directly correlate to GPU usage
My conclusion:
During development a lot of custom code (layout, event handling, etc..) has been introduced in order to fit WPF to the backend-driven architecture of the system as a whole. My guess is that due to some of the custom code the dirty-rect-mechanism of WPF has been broken. This leads to too much drawing activity and thus very high GPU usage. These innecessary activities lead to the problems described above.
Now I am looking for any advice where I should start my investigation. Or in other words: What are typical mistakes that a developer can make in order to break the WPF dirty-rect update algorithm. Any input is highly appreciated.
Many thanks and best regards!
Manuel
Thanks for the input. Let me clarify backend-driven: The UI is highly dynamic. A message from the backend defines the structure of the ui and the data to be displayed. Therefore, we do not have any xaml for the structure of the tabs, only c#.
In the meantime, I could solve the problem. I used Snoop and collapsed every element one by one while monitoring GPU usage. I found out that there was a very tiny pixelshader effect (DropShadowEffect) on one of the borders. As soon as I removed the effect, the GPU dropped from 80% to 1%. WPF drew correct dirty rectangles over small portions of the UI. Problem solved, case closed.
Things that seem interesting to me:
1. The tremendous impact that this small effect has on the GPU usage.
2. That it breaks the dirty-rect calculation.
3. Since it was not a BitmapEffect but a PixelshaderEffect I could not reveal it by disabling BitmapEffects in Perforator.
Thanks!
MM

WPF performance issue when resizing the window with lots of controls

I have a WPF window that contains a fancy image with roughly 200 controls (derived from buttons), all of which use one of my 5 templates (paths, shadow effects, etc). Agreed, it is a heavy window to draw. I can live with that.
My problem comes from resizing the window. Maximize/Restore take about 1-2 seconds, but manually dragging the bottom-left corner causes the system to hang for about 5-10 seconds. In that delay, the window is black & contains partial leftovers until the final result is shown. It looks amateurish and that, I can't live with.
Remote connection : using a remote account, I found that the window resize always takes 1-2 seconds, but doesn't draw the "intermediate" stages while I'm dragging the window borders. The result is as snappy as I would expect.
My conclusion is this: It's the redraws during the resize that are bottlenecks.
The inevitable question is this : how can I prevent redrawing the window until the resize is finished?
Thanks in advance for any ideas...
#Seb: I'm beginning to think WPF is
not designed for interfaces that go
beyond 2-3 controls at a time
Visual Studio 2010 and Expression Blend should be good counterexamples. Though Visual Studio sometimes freezes the bottleneck is definitely not in the WPF rendering.
#Seb: The inevitable question is this : how
can I prevent redrawing the window
until the resize is finished?
Simply set the window's content visibility to Visibility.Collapsed before the resize/maximize and make it visible afterwards. Though I think you asked the wrong question. Here is the right one
How to make my controls measure/arrange extremely fast?
And to answer it you should take a look at your code. Maybe you intensively use dependency properties in the measuring/arrange algorithm? Or maybe you picked wrong panels (e.g. Grid is slower than Canvas)? Or maybe... I stop guessing here :).
By the way, it's always better to launch your app under profiler and prove the bottleneck rather than assuming the place where it might be. Check Eqatec Profiler it's free yet powerful enough. VS 2010 also offers nice profiling features, though it's far from being free. And you may want to check WPF Performance Suite.
Hope this helps.
Let me know how this works... I am assuming that your root visual item is stretching to horizontally and vertically to fill your window with auto height/width. Get rid of the Auto height/width. On app start up set the dimensions of the root element. There is a FrameworkElements have a size changed event. Register for this on your Application.Current.MainWindow (maybe be a typo, that was from memory). Whenever this event fires, start a timer with a small interval. If you get another resize while the timer is running, ignore it and reset the timer. Once the timer fires, you now know the new size the user desires and that they have (at least for a short period) stopped resizing the window.
Hope that helps!
From Ragepotato's answer and your comment about needing to see roughly what the interface would look like while resizing, as long as you don't have your objects dynamically re-locating themselves (like a Wrap Panel) - you could take a screenshot of the window contents and fill your frame with it.
Set it to stretch both height and width, and you'd get a (slightly fuzzy) idea of what a particular size would be. It wouldn't be live while resizing, but for those few seconds that probably wouldn't matter..

Prevent WPF stutter / dropped frames

I've written a simple game-like app in WPF. The number of objects drawn is well within WPF capabilities - something like a few hundred ellipses and lines with simple fills. I have a DispatcherTimer to adjust the positions of the objects from time to time (1/60th of a second).
The code to compute the new positions can be quite intensive when there are lots of objects, and can fully load a processor. Whenever this occurs, WPF starts skipping frames, presumably trying to compensate for the "slowness" of my application.
What I would much rather happen is for all the frames to be drawn anyway, only slower. The dropped frames do not add any speed - because visual updates were pretty quick anyway.
Can I somehow force WPF to have my changes to the visuals be reflected on the screen regardless of whether WPF thinks it's a good idea?
Unfortunately I don't think there's anything you can do about this, although I will happily be corrected! WPF is designed to be an application creation framework, not a games library, so it priortises application performance and "usability" over framerate. This actually works very well when producing applications as it allows you to use quite rich animations and effects while maintaining perceived performance on lower end systems.
The only thing I think you might be able to try is push your movement code's Dispatcher priority down slightly to below Render (Loaded is the next one down) using something like:
this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, MoveMyStuff);
I don't have any kind of test harness to verify if that will help though.
This issue was fixed by using a Canvas with an OnRender override instead of creating and moving UIElements. This does mean that everything needs to be drawn by hand in OnRender, but it can now run at any FPS consistently, without skipping any frames.

WPF Virtualizing a Canvas

We have a series of rectangles produced inside a Canvas and they are nested in this order ScrollView>Canvas>VirtualizingStackPanel>Rectangles in the XAML.
There seems to be little information on Microsoft about under what senarios Virtualization is supported, and in cases where it isn't no error is thrown, it merely treats it like a standard StackPanel.
Given that our view has roughly 60 rectangles on the screen at any one time out of a total of about 800 on the whole canvas the loading times of about 5 minutes are unacceptably slow.
We have already tryed removing the ScrollView to no effect ( other than removing the scroll bars the performance didn't improve), and removing some of the other nesting elements, the net effect seems to be either nothing is displayed, or its displayed but still slow.
The best solution I've found so far a sample piece of free ware code VirtualizedCanvas but its very very limited and doesn't support anything nested inside it, infact the only input it takes is a collection of UI Elements.
This solution basically ignores the databinding and requires a you to pass a completed Canvas back to it, this renders all our existing code and converters pretty useless, and would be major rework to implement.
Is there a way to simply clip the Virtualize the Canvas to only draw our 60 on screen items?

Resources