Performance of C#/.net forms with lots of controls - c#

Does the number of controls on a form affect its performance? What if the controls are marked invisible? What if the several controls are visible, but entirely covered by only a few controls (like a panel containing a couple of controls)?
I'm asking this from a perspective of applications like 3d modeling packages, video editing software, etc. They've got hidden panels, tabs, rollouts, animated drawers and what not.
Has anyone done any such performance tests? Is considering this worthwhile?

Yes. Outside of the drawing, each control uses it's own window handle just by initializing it. So even invisible or hidden, it will affect performance.
The type of control makes a difference too. 3rd party or custom controls will sometimes be composed of multiple controls, each having it's own handle.
Usually the up front consideration for the amount of controls is done in the usability context and that generally should help avoid performance issues.

Without doing any performance test it's easy to say that too many controls has performance issue,
The memory usage increased (UI objects are very huge).
OnPaint and other message base
methods will be called (for control
or for parent in inheritance
hierarchy)

Related

Performance degrades after navigating to some pages

i have this weird problem with my WinRT app (Windows Phone only). The app is made of multiple pages, it uses an animation to show a side menu which mimics the hamburger menu in W10M. The animation and app performance are great when the app first launches, but after navigating to some pages (say 3 or 4 pages) the app performance gets worst and worst. I don't have any code that is running in the background on the UI thread or any other thread.
Is there something about navigation in WinRT i am missing? It is really weird and i don't know what is causing it.
Here are some considerations that impact performance in XAML.
Depth of the visual tree. You can drag on two controls, but those controls represent several nested controls - things like borders, buttons, and panels. Running your app and looking at it with the Live XAML Tree viewer can give you a hint if a control is more complex than you want. Also, keep depth in mind when you build your UI. Favor simple controls like RelativePanel and standard, non-re-template control.
Construction versus loaded logic. It's not uncommon for developers not yet familiar with XAML to implement complex logic in inappropriate places. For example, you might, in the constructor of a sub-classed control, tell it to go get some data or test some expensive condition. Ideally, you will use Loaded of a control, or OnNavigatedTo of a Page if you have this type of logic, and use async if you have the option.
Data binding. Data binding is awesome but it is also expensive. You can use it in a few dozen places on your page an not likely to ever make a difference, but if you start to use it everywhere and for everything, it can be really expensive. The easiest remediation is to reduce the bindings in your page. Next, you can change your bindings from Mode=OneWay (which is the default) to Mode=OneTime wherever you can. Next, you can switch from {binding} to {x:bind} wherever possible. Remember, binding is not wrong, it's just expensive, so use it only when appropriate.
Too many records. If you have a repeater like a ListView or GridView then you might have too many items appearing at one time. This is a big deal, especially on load. It's rare that the real cost is fetching the data, it's typically rendering the data. If your item data template is complex, then your visual tree depth may be multiplied several times with each record. Loading fewer records at load and then showing more over time is one approach. Using x:Phase is another great approach. Simplifying your item templates is another approach. Minimizing data binding in your item templates can help. But, the best you can do is to run the diagnostics tool and look to see what's causing it. It might not be your ListView at all.
Unused Visual States. Developers are smart to use visual states. However, some states they define are for edge cases and show only in certain circumstances. The XAML for those views may never appear, so they mark their Visibility to Collapsed. This is okay. But if you go one more step and use x:DeferLoadingStrategy you can prevent the cost of that XAML parsing and rendering at startup. When the visual state reveals that XAML, it will automatically be realized by the platform. You're the winner, so is the user.
So, 5 helpful tips to help your pages load faster.
Odds are, your reason is going to be something else :)
ONE MORE THING
Are you allowing your pages to be removed from memory? Is it possible that in your implicit code in your code-behind you are subscribing to a static or global event? Maybe you need to unsubscribe in your OnNavigatedFrom override. Since the problem gets worse over time, it sounds like it might be a memory issue. Though, that is just a guess. It's a common C# slip up.
Best of luck

ReactiveUI - View Locator performance

In my WPF application which makes use of ReactiveUI, I've noticed an area of poor performance.
I have a view-model which contains a lot of other lightweight view-models (think 30ish). These nested view-models are simple, usually representing a button each. They're all displayed within a user control, inside an ItemsControl which is wired using ReactiveUI's OneWayBind. This means that each item is displayed using ViewModelViewHost.
So, the problem
On my powerful desktop PC, when I navigate to this view-model, there is a noticable delay between pressing the "go-to-view-model" button and the view changing, around 0.5 seconds. When I run the same software on a Power-PC, the delay is nearly 4 seconds. This is a pretty big issue from an UX point of view.
What I've learned
I tried profiling and debugging my code for a long time, and found no problem areas. Zilch (note: using JustMyCode in VS so ReactiveUI didn't show up). I did however, find a way to remove the issue. Instead of binding to the ItemsControl.ItemSource with OneWayBind, I did so in XAML, as such:ItemSource={Binding MyViewModels} and setting the DataTemplate manually. This results in a much quicker transition.
When you bind with OneWayBind with an ItemsControl, a ViewModelViewHost is automatically created for you, and the ViewLocator is used to find the view for your view-model. I'm assuming this is very slow for some reason.
Question
Is anyone aware of how I can get around this performance hit without having to manually define lots and lots of data-templates for an ItemsControl? If I have view-models of view-models of view-models, then things tend to get ugly very quickly. From my past experiences with Caliburn.Micro, the view-location conventions were very quick, so I'm also wondering if I'm not quite using ReactiveUI properly, and that there is an alternative approach which is quicker.
Thank you.
TLDR;
ViewModelViewHost as a DataTemplate for ~30 view-models causes views to be very sluggish when initially loaded, leaving the UI to look as if it has crashed. Is there any way to avoid this?
I believe the root cause of this issue is an implementation issue of TransitioningContentControl.
This control (which has many existing implementations all over the place, most of which originated from Silverlight one AFAICT) will cause an extra load/unload transition when navigating out of a content.
The current control will trigger Unload/Load/Unload when navigating out, instead of single Unload. This issue is referenced in many places.
When used in RxUI, this bug causes WhenActivated to be called on the leaving View, causing performance issues, especially if the current view is complex.
TransitioningContentControl should be re-written to avoid this extra transition, here's an sample implementation which doesn't suffer from this issue.
I've run into this exact same problem before.
Essentially, you want to show/hide, rather than create/destroy.
Creating a new visual tree is lots of work, and you will typically get delays of seconds or more when you switch tabs.
Now if you create everything, then collapse what you dont need and show it on demand, suddenly everything updates in an eyeblink.
It may take a bit of refactoring to do this, and the code may not look as clean, but it sure as hell runs blazingly fast.

.Net Winform Controls (MenuItem, ToolBarButon, ContextMenu, Splitter etc ) not releasing my User Control. A Memory leak issue

I have a C# WinForm User control made up of many child user controls such as MenuItem, ToolbarButton, ContextMenu, Splitter, Panel..etc..I open and close this user control many times in a ActiveX container. I see its it leaks memory every time it is open and close. I called GC.Collect in the dispose of this control and found that it leaks less memory now. but still it leaks.
I have also called the dispose on all other child controls MenuItem, ToolbarButton, ContextMenu, Splitter, Panel..etc in Dispose method of User Control but still i see that my User control is not GCed.
Please find the image from .Net profiler..you can copy the link of image in other tab of browser to see it large aaTrendControl is the name of my user control.
Find the image when I click on one child control instance in
Why MenuItem and ToolbarButton control are not releasing my UserControl even when I Dispose them..Is anything I am missing.
Simply calling GC.Collect will not release everything that went out of scope in one go. Garbage collection is allot more complicated. There is a concept of generations. Referring to objects that in turn refer to objects place them in different generations, and one call to GC.Collect will most likely only remove the last generations in one cycle. Calling it multiple times will also have little effect. If there's not much to do it may just ignore the call and return with "I'm done".
I recommend you read the excellent book Under the hood of .Net Memory Management. It's a freely downloadable PDF with allot of details on what's going on.
From your story, it is likely you are creating many "handles". Every control on a form has a so-called handle. These are native windows resources, that need to be "pinned" in order for windows to send messages to them (mouse-over, click etc...). Pinned objects are even more complicated because the GC cannot simply move them to another part of memory when defragmenting, so excessive allocation of controls can cause fragmentation problems. In the old days (before windows XP) there used to be a hard limit on the number of handles that a process would be allowed to allocate.
You may want to consider using GDI+ a little more to save out extra controls. For example, when creating excel-like grids, it is custom to draw the whole grid on one canvas, and only when the user clicks (or focuses) on a single cell, overlay it with a textbox or dropdown control in-place. Creating separate controls for each cell would have an enormous overhead, even on a modern computer.
It's good practice to re-use controls instead of disposing them and recreating them. Reusing controls will have a huge positive impact on performance. This because of the fact that visual controls require a context switch between your process and the OS in order to acquire a handle. Unfortunately I don't know of a good book on windows forms. I learned most of the details from my old Delphi 2 books, almost two decades ago. I might be outdated on some details, but the essential basic concepts in WinForms have not changed since then. Even when you work with .Net, an old book on the native Windows API's should help you get an idea on what's going on under the hood.
.Net will take care of the memory management saving you quite some headache, but fragmentation can cause problems, which can be overcome by reusing visual objects instead of disposing them. If you really need to call GC.Collect in your code, it usually implies you are doing something else wrong (exceptions exist though).

Does containers nesting in XAML affect rendering performance?

Does the rendering performance reduce seriously in case when WPF application's XAML contains a lot of nested Grid, StackPanel, DockPanel and other containers?
Really the answer is simply "yes". More of anything will use more processor time. SURPRISE!
In the case of WPF, elements are arranged into a hierarchical scene graph. Adding levels of depth to this graph will slow your application more than adding siblings to existing elements. You should always strive to keep the depth the graph low. Consider using Grid instead of nesting StackPanels.
So why is depth more important than raw element count? Well, depth generally implies;
layout dependency - if a parent is re-sized a child is likely to be re-rendered.
occlusion - if 2 elements overlap, invalidating one will often invalidate the other.
recursion - most graph operations are CPU bound - they depend entirely on CPU speed and have no dedicated hardware support (the renderer uses your graphics chip where possible). Cycling through levels of the graph for resources and layout updates is expensive.
Concerning occlusion, the BitmapCache class can help greatly!
When you create a very complex UI, with lots of nested objects and DataTemplate with lot of elements, you can impact seriously the performance of the App, because the bigger the UI Tree, the bigger it will take to render, and if the framework cannot render in 30FPS you will start to see performance drops. You should use the most lightweight panels you need in order to avoid extra logic you wonn't need. Here are some performance tips in order to make you App faster:
http://msdn.microsoft.com/en-us/library/bb613542(v=vs.110).aspx
WPF uses MeasureOverride and ArrangeOverride methods inorder to render UIElements. MeasureOverride measure the UIElements width and size based on the Parent controls Width and Size. ArrangeOVerride method will arrange the UIElements at runtime based on these measures. These methods are optimized for faster performance and should not cause any rendering performance issue.
But there should be a capacity where these methods can handle UIElements within a minimal time. If this limit exceeds then there should be performance issue.
eg: Suppose a bike can carry 2 person. if 5 persons overloaded what will happen :)
Jet Brains .Trace is a tool to analyze the performance issue which will helps to see these two methods

Efficiently creating many instances of a winrt metro control

I want to be able to create a few hundred instances of a winrt control (a search result control) in a C# project. The problem is that doing so takes too long (tenths of a second or worse) and must be done on the UI thread, creating stalls and delays in showing results.
For now I've bypassed the issue by pre-caching many instance of the control during startup. This approach works, but affects the startup time (profiling shows 40% of processor time near startup is spent caching these controls) and creates details to be managed, like the size of the cache.
I think the issue is that every time the control is instantiated redundant work, like re-parsing XAML, is done by the underlying framework. Maybe there's a way to avoid repeating this work? Maybe I can cheaply clone an existing control? Does anyone have ideas?
You could do the pre-caching in a parallel thread. Will make less of an impact on startup time on multicore processors
searchresult.memberwiseclone wil give you shallow copies. It might be faster, not sure
Could you use just one searchresult and fill it with the right data just before use? In that case there is no need to create a lot. Just use one as a re-usable container.
If the time is spent when adding the controls to the parent forms you could use
suspendlayout/resumelayout (this is win32)
setting parent to invisible and back to visible when you are done
Is there another way to do the same things faster? (competing control, 3d party etc)
Forenote: it's been awhile so Microsoft may have fixed the win8 app UI virtualization by now. I haven't checked.
What I ended up doing at the time was just hacking together my own UI virtualization to work around the issue. Basically: caching controls and re-using them to display the viewable data (using a binary search tree to efficiently query what can be seen). I wrote a blog post about it.

Categories