I'm developing a Silverlight application that displays items in a listbox control and I've run into a bit of a performance issue.
Each item in the listbox is a custom stackpanel with some formatted text and such.
When I've got a list of 500 or less items the listbox works fine, but loading more than this causes problems. At 1000 items, Silverlight will consume 10% cpu, even if I'm not doing anything, at 3000 items the cpu constantly uses 32-36%.
This is on a dual core machine, on an older machine I tested out on the cpu usage goes way up.
This also effects the framerate, I'm getting 6fps with a 3000 item listbox, which makes the application sluggish.
Does anyone know what might be causing this? My first thought was that silverlight is trying to render all the items, even though the items are off screen... this seems to be consistant as if I insert items with their Visability.Collapsed, the extra cpu overhead is not present.
PS: I'm running in windowless="true" as I need to display some html ontop of my silverlight form.
You should use the DataGrid in Silverlight 2 because it supports UI Virtualization. It has been tested with millions of items and will only create enough visuals needed to display.
Your guess is basically correct. Although Silverlight does not attempt to render all 3000 elements in the ListBox, it still needs to create 3000 ListBoxItem objects, which in turn get Measured and Arranged during layout time, etc, only for them to get clipped at render time. Layout happens much faster when the elements are Collapsed (since there is basically nothing for layout to do in this scenario).
WPF has VirtualizingStackPanel which would solve this problem, unfortunately Silverlight doesn't have this element.
+1 for using the Silverlight DataGrid in this scenario, make sure you have the latest version installed as the default Silverlight SDK version has a few bugs.
Another option is to use the free Silverlight DataGrid Control available here. One of it's features is also a Virtual StackPanel Row Container which means the grid can handle an unlimited number of rows.
Compare the performance of each and see which works best in your situation.
Just an observation - it looks like this is not an issue anymore with Silverlight 4. Adding 100K elements to a data-templated list box is instantaneous and it renders just fine as well.
This helped me: Silverlight DeferredLoadListBox .
It is written by David Anson, a Microsoft employee.
The DeferredLoadListBox derives from ListBox but has much better performance.
Related
I'v run into an preformance releted problem with a DataGrid in an Sliverlight 4 application that I'm currently working on.
In our application we have a DataGrid which is quite huge, up to 4000 rows.
Its obviously extreamly slow to scroll a grid this big. Lets say you grab the tracker in scrollbar at the top and drag the mouse courser to the bottom. The tracker eventually reaches the bottom but it takes a few minutes.
It seams like Silverlight wants render ALL rows that it passes.
Using the ScrollToPercent method works like a charm though, so what I would like to do is to use ScrollToPercent when you release the tracker.
You follow? Lets say I grab the tracker and then I can move it up and down the scrollbar WITHOUT the view changing, but as soon as I release the tracker it should trigger a ScrollToPercent.
Did that make sense? Is this possible, or do you have a suggestion that in another way can help me solve this problem?
I'm experimenting with creating a metro style app with Visual Studio 2012, I am not the most experienced designer but one thing with my applications is confusing me.
I have been working with 'basic pages' instead of blank ones for the different pages in my application for design consistency, however it seems that these 'basic pages' have a strange behaviour. Every item I place on the page (buttons, text boxes, etc) will all slide in one by one when the page opens. For example if I run the application and navigate to a page with 10 buttons, it will do a brief animation where each button will slide in from the right side to the left side. When dealing with a large number of items on one page this can take a lot of time as each item slides in seperatley.
Looking at the properties for each item I have been able to change the direction it slides in while loading the page by changing the flow direction. Also with a bit of research I am thinking it could potentially be due to either the metro style 'enterPage' or 'enterContent' animations, though I can not be certain.
I have tried to experiment and figure this out, and search to find out what causes this so I can modify it (Ideally I would like to just group items together to slide in with each other) however it's kind of a difficult thing to search with vague words, so I'm asking here.
What is causing this and how might I go about modifying it?
EnterPage shouldn't be sequencing the animations. They do offset some of the animations of a number of elements, but it shouldn't be each one sequentially.
Are you using WinJS navigation?
Well after a bit of experimentation I figured out that putting all my page content inside a grid made them all come in at once like I wanted. I probably should have tried that earlier but everything was already inside an outer grid for the page, so I thought that woulda handled it.
I don't quite understand it fully, but that works for now.
I am working with flex for the last two years on some desktop apps. Until now I never had any performance related issues but today as we completed a mobile application for the iPad, I'm facing a challenge, the application is incredibly slow on the iPad.
http://i.stack.imgur.com/qkbWn.png
Slow, means that when I press a button in the menu to change the splitview I must wait something like 5s. Then scrolling is really slow two, with less than one fps and my TextInput starts to bug (the text is not in his box anymore).
I started to read a lot of blog post and presentation about optimisation for the mobile platform and then I rewrite some of the components I use. I removed the SkinnableContainer for instance and replaced it by a VGroup including some actionScript based drawing.
Now what you see is a VGroup (the dark grey one) containing some others VGroup (the group with title here) and then each widget is an HGroup with a label and a Widget. I only use Label and TextInput for the text.
Creation time is slow even (several seconds to create the view) for another page where there is only 4 text widget on it, or another one with only a list with a custom item renderer where each row is a set of 4 labels.
The whole things is cabled with RobotLegs, with nothing fancy, one models is injected in the view and at the beginning I set a member variable on the view with this object to bind my variables.
Frankly my thinking right now is : it smells fishy because if I've done everything right it is impossible to have such low performance and thinks that flex is competitive on the mobile platform. So right now I'm trying to disable the application piece by piece to try to locate what could slow it like that. I've got a couple suspects to check, for instance I've got some binding warning to check, and then see if robotlegs has got its share of the problem.
So my main question here is what do you think, and could you have some ideas about "is there a problem" and "how do we solve it".
Thanks
Run profiler for startup and separatelly for each operation that takes longed that it needs. Then prioritize the problems and try to solve them with basic optimization techniques.
Some problems you will not be able to solve fast - e.g. time for creating big components. The only option there is to rewrite those components with AS3 without MXML, styles and anything. I'm sure that flash.text.TextField is created many times faster than mx.controls.Label. The same for other components.
When component is created, it can be reused at a very low price. In your app there must be a lot of places where you recreate while you can reuse old components. It will save you memory and time.
Layouts tend to redraw even when it's not needed. If you have a lot of nested layouts, find the most critical places and replace a series of layouts with one custom layout or even component.
This all is very developer time consuming. At the end you will not get a smooth app anyway, but I believe that it can become usable.
I have a page in my WP7 app that I build dynamically. I create and add 60 user controls to a grid and it takes around 5 seconds. I need to find a way of speeding this up.
The process is as follows:
Create user control
Add new grid row definition
Set the value of the control row property
Add the control to the grid.Children collection.
It is step 4 that is taking the time. I'm guessing that each time I do this the visual tree is getting re-built.
Is there any way of telling the grid to only re-build the visual tree after I have finished updating the children collection?
Or is there another better way of doing this?
UPDATE: The List Picker control from the WP7 Toolkit was causing the problem. When I changed to one I wrote myself the time taken to display the page on a phone reduced from 25 seconds to 1 second.
The/your aim is to try and reduce the number of times you update the visualtree.
A few suggestions:
Try including (some of) the items in the page by default but just change their visibility depending on what you need.
Build the whole grid in code and add it to the page in one go (rather than a line at a time)
Depending on your content, you could try using a ListBox and alternating the template used for each row to get different content displayed.
The technique which will be best for you will depend on what you're actually adding to the UI. You'll need to test to see what is best for you.
If the UI virtualization (i.e. ListBox) helped, the problem must be in your controls. Templating, bindings, converters, using Xaml instead of C# code, unnecessary Xaml constructs (such as element names), overcomplicated visual tree (e.g. unneeded grids) etc. - those are the things that can degrade the performance.
If you suspect incremental visual tree rebuilds (I don't think so), then simply debug MeasureOverride/ArrangeOverride methods.
I guess this article might give you more tips. I described there how we optimized a similarly complex control - MonthCalendar with 126 sub-controls. Control load time decreased approx. 5x!
Usually, when a View requires a lot of bindings, or some UI Elements like a Bing Map, it takes a "while" to load (like between half a second and a second).
I don't want a delay between a "tap" action (like tapping an element on a ListBox) and the navigation action (displaying a new page).
I don't mind displaying the page progressively. For example, for a Bing Map, I don't mind displaying a black page with only a title, and a second later, having the Map appear.
What are the best practices ? It could post a sample if i'm not clear enough
edit: I'll keep the question open for a while, so other can answer. Thanks Matt and Mick for awesome answers. I'm already working on some improvements. The major one being binding my controls after the page loaded.
It's expected on resource constrained devices that non trivial actions will take at least a little time to execute.
The most commonly recommended best practice for dealing with this is to use animations to give the user the impression of perceived performance. This has been a recurring recommendation throughout the CTP and Beta phases by the product team and in presentations at Mix 10 and Tech Ed 2010.
Page transitions are a common approach to this.
Discussed here by Kevin Marshall, prior to inclusion in the November toolkit.
WP7 – Page Transitions Sample
And here, referencing the control in the toolkit.
Transitions for Windows Phone 7
There are also a number of very basic optimisations you can do that will give you some bang for a little effort.
don't name controls that you don't reference in code
use background worker to load any data to avoid impact the UI thread (already busy loading your page) and fire this off after the page is loaded (disable any controls not usable in leui of this) (Phạm Tiểu Giao - Threads in WP7)
use httpwebrequest over webclient for the same reason (WebClient, HttpWebRequest and the UI Thread on Windows Phone 7)
I would also reiterate Matt's suggestion for not loading controls that aren't used initially.
If you decide to go the extra mile, there is more you can do to optimise page loading. These two posts are worth absorbing in that regard.
Creating High Performing Silverlight Applications for Windows Phone
WP7 Development Tips Part 1 - Kevin Marshall's Epic Work Blog for Awesome People
If using Listboxes, also familiarise with Oren Nachman and David Anson's
WP7 Silverlight Perf Demo 1: VirtualizingStackPanel vs. StackPanel as a ListBox ItemsPanel
Keep a low profile LowProfileImageLoader helps the Windows Phone 7 UI thread stay responsive by loading images in the background
Never do today what you can put off till tomorrow DeferredLoadListBox (and StackPanel) help Windows Phone 7 lists scroll smoothly and consistently
and be sure image sizes are optimised for their display size.
My suggestions/recommendations:
Create and navigate to the new page as quickly as possible.
Display the page with placeholder content while it loads (if appropriate).
Give an indication that something is happening while the page loads. An indeterminate progress bar (use this one) is the convention on the platform.
If it's not possible to use the page until all controls are loaded, then prevent access to the page. A semi-transparent object displayed over the entire page is a common technique to not only prevent touching of controls but also to indicate that they can't yet be touched.
If possible/practical set the size of the items in xaml/code to prevent relayout due to resizing once an item is loaded.
Try delay loading of items which aren't on the screen initially to get the perceived total load time down.
and finally:
Optimize everything to get the load time down and the application as responsive as possible.