ListBox performance: WinRT vs. WP8 vs. WPF

With the raising popularity of WinRT and WP8 the demand for building complex UIs for managed apps increased significantly . A heavy UI which if not handled properly can lead to poor user experience.

This post will analyze the performance penalties of adding lots of visuals to a ListBox, present the traps of the “easy way” and suggest an alternative for overcoming them.

The problem

Take the following code which creates a collection of items and acts as a ItemsSource to an ListBox. The ListBox renders its items as Rectangles:

        private void CreateRectangleItems()
            var collection = new ObservableCollection();
            Random random = new Random();
            for (int i = 0; i < 1000; i++)
                collection.Add(new Item()
                    X = random.Next() % (int)this.ActualWidth,
                    Y = random.Next() % (int)this.ActualHeight

            this.DataContext = collection;

       class Item
              public int X { get; set; }
              public int Y { get; set; }
While the code works just fine, it can consume up to 50 MB of memory, which is of course not ideal. Furthermore, the higher the number the items, the higher the memory consumption and the longer the time it takes to generate them e.g. 3000 items can consume more than 100 MB and take 2-3 seconds to be generated. Check out the graph below for a better picture of the behavior. I will call this approach the visuals approach.
Winrt Listbox memory consumption

The solution

Recently I found an efficient way of displaying large number of items while keeping the memory consumption low. Here’s how: replace all the visuals with a single Path visual built based a geometry where you can put as many elements as you want.
I will call this approach the geometry approach and here’s the code for a possible implementation:

        private void CreateGeometryItems()
            var collection = new ObservableCollection();
            var random = new Random();
            var item = new GeometryItem();
            var group = new GeometryGroup()
                FillRule = FillRule.Nonzero

            item.Shape = group;
            for (int i = 0; i < 9000; i++)
                group.Children.Add(new RectangleGeometry()
                    Rect = new Rect(random.Next() % (int)this.ActualWidth,
                           random.Next() % (int)this.ActualHeight, 10, 10)

            this.DataContext = collection;
This change brings significant memory consumption improvements. Check out the improvements in the chart below (the geometry approach is marked with green)

listbox winrt memory  consumption

After seeing such massive improvements I got curios to see how this technique would work for other platforms like Windows Phone 8 and WPF.

For WP8, the results are pretty much similar, the geometry approach is couple of times faster and less memory expensive than the visuals approach.

listbox wp8 memory consumption

Surprisingly, on WPF the visuals approach is not as memory expensive as is on WinRT or WP. However, the geometry approach is still twice as fast and memory efficient.

listbox wpf memory consumption

Bottom line: if you want to display and manipulate 1000+ visual elements in a ListBox consider the geometry alternative presented above, especially when using WP8 or WinRT.

One more thing 🙂

I found this technique while I was working on my Win8 app Puzzle Frenzy.

The app is available in Windows Store, check it out and tell me what you think:

You can also give your feedback on app’s review page or on app’s Facebook page

Happy coding!

Puzzle Frenzy home page

One thought on “ListBox performance: WinRT vs. WP8 vs. WPF

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s