Silverlight performance with a large number of Objects Org Chart - silverlight

I’m working on a org chart project(SL 3) and I’m seeing the UI thread hang when the chart is building around 2,000 nodes and when it renders it takes about a min and then FPS drop to a crawl.
Here is the code flow.
Page.xaml.cs calls a wcf service that returns a list of AD users. Then we use Linq to build a collection of nodes to bind to the Orgchart.cs
OrgChart.cs is a canvas and displays a collection of nodes and connecting lines.
Node.cs is a canvas and has user data can contain children nodes.
NodeContent.xaml is a user control that has borders so I can set the background, textblocks to display user's data, Events that handle the selected and expaned nodes, and storyboards that resize the nodes when they are selected or expanded.I noticed during hours of debugging , here in the InitializeComponent(); section where it loads the xaml it seems to be where the preformance hit is happening.
System.Windows.Application.LoadComponent(this, new System.Uri("/Silverlight.Custom;component/NodeContent.xaml", System.UriKind.Relative));
So I guess I have two questions.
Can threading help in any way with the UI thread hanging while drawing the nodes?
How can I avoid the hit when calling this user control?
Any advice or direction anyone can lend would be greatly appreciated.
Thanks,
KC

Sounds to me like your UI has a natural point for comparmentalising the load by loading UI for nodes on-demand.
You have nodes that can be expanded and collapsed. Only load the UI for the nodes currently expanded. As the user expands a node then load the UI for its child nodes at that point.

As far as doing anything with the UI threading is going to get you nowhere. You might be able to do some data massaging on background threads, but if you mess with any objects that are databound to UI on a background thread you are looking for trouble. You will really need to split out this work from the UI, and then invoke it back over.
My guess is that Siverlight is simply taking a while to draw all of the nodes. We have an application which draws around 100 fairly rich widgets. Only about 20 or 30 widgets are visible in an ItemsControl host a wrap panel. We ended up getting better performance by using a virtualizing wrap panel, which doesn't actually instantiate the hidden UI elements until they are needed. There are some trade-offs here, and we are still working the problem, but the page loads much faster this way. You might take a similar strategy drawing your nodes, only loading the nodes that need to be visible. Also, you could load portions of the tree onto the drawing surface in lumps. Perhaps take the first 100 records and draw those, then draw the next 100, etc.

Related

Suspend painting of underlying grid control

We are facing an issue, wherein we need to suspend grid painting for some time. We are using devexpress DXGrid bound to XPInstantFeedbacksource. We have a requirement of refreshing source every 2-3 seconds to get the updated realtime data which is huge (around 40 -50 thousand records in a day).
However the refresh method of the above mentioned source binds the grid asynchronously and when it does so, it causes some kind of flickering onto grid. Internally it captures layout of grid before refresh and renders it back in postrefresh phase.
I have tried many things like wrapping the refresh call in bigindataupdate and enddataupdate, but it doesn't seem to work.
However, one thing which looks interesting to me is using Win32 api to suspend layout painting for some moments and resuming it.
I found something at
How do I suspend painting for a control and its children?
which works well for Winforms, but in WPF as far as I know, individual controls share window handle. And method call
SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
uses control handle to interact with WIN32. Also, I observed that if I suspend layout for window underlying grid still gets painted which is strange to me.
I just want to know , if I am going in right direction by suspending grid layout to avoid flickering and if yes please suggest some way to achieve this.
Thanks,
Gurpreet

What is the best practice for creating customised graphical display of hierarchical data in WPF

I would like to be able to display network-tree information (stored in hierarchical data structure), as in the example shown in here:
In the diagram, I have a number of hosts (top-level nodes) - one of which is considered the 'Master' and therefore rendered differently from the other top-level nodes. Each node can have multiple sub-nodes (probes). The lines between the nodes show connections and if any of the connections goes down, the line changes as shown between Hostname2 and Probe2.3. Any node selected (host or probe) should also be rendered differently.
I am using Prism/MVVM and I'm trying to keep the code as clean as possible, but I'm not sure of the best way forward for displaying this data.
I have considered using a TreeView but I cannot think of a clean way of creating the links between nodes. I also considered creating a custom panel, but I'm not sure that's the most appropriate and wouldn't know where to start. Then I thought of creating a custom ItemsControl, as it would be nice to use the DataTemplate and HierarchicalDataTemplate. I could also create a UserControl that contains a canvas and do everything in the code-behind there but it doesn't feel the best way.
I'd be grateful for opinions, example code, links or any suggestions you may have.
You're in luck, last year I had to write something very similar for my current job. I can't give you any of my code but I can lead you in the proper direction.
I found a directed graph collection class available here: http://msdn.microsoft.com/en-us/library/ms379574(v=vs.80).aspx#datastructures20_5_topic3.
I also use a Radial Panel I found on MSDN: http://msdn.microsoft.com/en-us/library/ms771363(v=VS.90).aspx. This allows multiple nodes to draw in a geometric shape. So if you have 3 nodes, they draw a triangle, 4 a square, 5 a pentagon, etc...The more nodes you have, the more the layout becomes a circle. This wouldn't work for you, but if you follow the link it shows you how to create a custom panel with a custom layout. It could be beneficial.
I then used a Canvas as the stage, with the RadialPanel as the Canvas' child element. Each node is just a WPF UserControl with an ellipses background that is added to the RadialPanel. The directed graph collection then become a collection of node view models. I store where the node is connecting, almost like a linked list. This allows me to traverse my graph collection easily without having to iterate each node to find the nodes I'm looking for.
There are some tricks involved in drawing to ensure the layout is proper, especially when drawing your connecting lines. See this StackOverflow post I made: WPF and C# - Issue with GeneralTransform and UIElement.TransformToVisual. It has a link to an image of my node graph so you can compare our graphs.
This obviously isn't everything, but I think it's a good start. For me, I couldn't really override any current controls to do exactly what I needed, so I went the hard way. The trade off is a lot of work in the code-behind and view models, but I also control the major aspects of how it's drawn. I this helps.

Rendering Thread still slow after Virtualization

At a high level my application is applying about 5 different DataTemplates to a set of ListBoxItems based on their type. These items are laid out on a canvas at specific x, y points. I implemented virtualization on my ListBox and it did not seem to improve the time it takes to complete the rendering thread's processes. It still takes about 8-12 seconds for the UI to be completely loaded and usable by the user. I thought virtualization would help fix this problem but after looking around it looks like it only helps process scrolling large amounts of data. Am I correct in this assumption and does anyone else have any other tips for improving the rendering thread. This is the only problem I am having and then my project is complete. Thanks StackOverflow!
Virtualisation means that only the items you have visible are created, then dynamically destroyed/new items created as you scroll. The alternative is all UI controls are created for all items at once.
It sounds like you have bigger problems with the rest of the app. Do you perform all loading operations on a background thread? Is the UI control tree very complex indeed? Are you displaying 100s or 1,000s of items?
We also had a lot of trouble with performance in WPF. Best way is of course to profile your application. We use ANTS Performance profiler for that, but any .NET profiler will do. We got a huge performance hit, because of the lookup of our XAML Resources. Thats the advice i can give you:
Try to minimize all resources in XAML. But not only that, also try to minimize the amount of XAML files you have. One thing you can try is to defere the loading of complex parts of your DataTemplate. Similiar to what happens when you load a JPEG in a browser, first you will see a pixelated image which will be finer after it finished loading the JPEG. To accomplish that, use a simpler DataTemplate at first and then if this is visible only load the complex template on demand or after a while.
But without more information of your specific problem, we can only guess. This is an old question of mine about a similiar subject, maybe this will help aswell.
Yes, ListBox virtualization is for scrolling. When you have a large number of items in a ListBox, enabling virtualization will make only the visible items (+ a few extra items for scrolling) render, and scrolling the ListBox replaces the data in the rendered items instead of rendering new items.
If you were to post some code, perhaps we could assist you with some performance tweaks

In what way a WPF Wrap panel is slower that we need virtual wrap panel

I hear a lot about the wrap panel being slower to load things and hence we need a virtualising panel.
Can somebody give me a small wrap panel sample where it can be proven it is slower to load etc that it needs a virtualising panel please.
I set a wrap panel as a panel control for a listbox, and added 10000 string objects to it, and it was not a problem. I am sure my sample was silly, maybe i have to write a business object and create a larger data template to see this problem in action.
Kindly show me a sample that proves wrap panel without virtualisation is slower.
Thanks.
I think the performance issue depends mainly on the number of visual objects in your tree.
The default ListBoxItem template consists of a low number of elements (a border and a textblock i think). If you have a template that creates a complex visualization of lets say 100 visual elements per item you get a fairly large amount of visuals depending on your item count.
This is the reason why the normal panel is slower at load time, because it has to create all the objects at startup whereas the virtualising version only creates visuals for the visible items and disposes no longer displayed visuals.
In addition this has also implications on memory usage
I recently needed this functionality when making a insert symbol form. Using a listbox with normal wrap panel as the items panel - load time would take up to 5 seconds.

Windows Forms Application Performance

My app has many controls on its surface, and more are added dynamically at runtime.
Although i am using tabs to limit the number of controls shown, and double-buffering too, it still flickers and stutters when it has to redraw (resize, maximize, etc).
What are your tips and tricks to improve WinForms app performance?
I know of two things you can do but they don't always apply to all situations.
You're going to get better performance if you're using absolute positioning for each control (myNewlyCreatedButton.Location.X/Y) as opposed to using a flow layout panel or a table layout panel. WinForms has to do a lot less math trying to figure out where controls should be placed.
If there is a single operation in which you're adding/removing/modifying a lot of controls, call "SuspendLayout()" on the container of the affected controls (whether it is a panel or the whole form), and when you're done with your work call "ResumeLayout()" on the same panel. If you don't, the form will have to do a layout pass each and every time you add/remove/modify a control, which cost a lot more time. see: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx
Although, I'm not sure how these approaches could apply when resizing a window.
Although more general than some of the other tips, here is mine:
When using a large number of "items", try to avoid creating a control for each one of them, rather reuse the controls. For example if you have 10 000 items, each corresponding to a button, it is very easy to (programatically) create a 10 000 buttons and wire up their event handlers, such that when you enter in the event handler, you know exactly which element you must work on. However it is much more efficient if you create, lets say, 500 buttons (because you know that only 500 buttons will be visible on the screen at any one time) and introduce a "mapping layer" between the buttons and the items, which dynamically reassigns the buttons to different items every time the user does something which would result in changing the set of buttons which should be visible (like moving a scrollbar for example).
Although, I'm not sure how these approaches could apply when resizing a window.
Handle the ResizeBegin and ResizeEnd events to call SuspendLayout() and ResumeLayout(). These events are only on the System.Windows.Form class (although I wish they were also on Control).
Are you making good use of SuspendLayout() and ResumeLayout()?
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx

Resources