One of the most important aspects of a Windows Store app is its performance: an end-user will simply not keep on using your app if (s)he has to wait too long to complete the task (s)he’s using it for – after all, for most apps, there will be loads of alternatives. For Windows 8.1 XAML apps, quite a few things changed concerning performance when you compare it to Windows 8. In this session we’ll cover those topics as well as learn about performing tasks in parallel, offloading tasks, keeping your UI thread responsive, data and UI virtualization, overdraw & analyzing performance… In short: if you’re serious about developing a Windows Store app and you want to learn how to ensure you keep it fast & fluid, you’ll want to attend this session.
 Test. Okay. Everyone can hear me, I guess? Okay. Our last session of the last day of great conference. So I'm very glad some people decided to stay until the end. And I hope I'll make it to a while. I'm going to start by introducing myself. My name is Kevin. I'm a solution architect, mainly focusing on mobile applications. I've been at the same company, Real Dolman, Belgium company, for about 10 years. So the things I'm currently doing, it's mainly back-end stuff. So mainly architecture stuff. So we can make applications cross-platform for mobile clients. One of those mobile clients we tend to make is a Windows Store app or a Windows Phone app even. And when you think about Windows Phone app, Windows Store app, that's XAML in my case, then what we often see are problems with performance, even now. So that's what this session is about. It's really about tips and tricks to make your app perform great. If you want to reach me afterwards, my email address is on there. That's my personal email address. But the easiest by far is Twitter. So that's the easiest way to reach me. Okay. So let's have a look at what we're going to look at today. I'm going to start with a XAML architecture overview, because it's quite important to know what's going on behind the scenes so we can understand what we need to do to get our app performing well. So that's the first thing. And then we're going to dive right into some XAML performance tips and tricks. By this, I mean these are the tips and tricks on how to organize your XAML, how to write the XAML elements to ensure that performance is great, and what writing them wrongly can have as an impact. Now, if you're talking about performance, we also need a way to measure this. And there's a few ways of analyzing performance. It's mainly memory analyzing, by the way, not performance profilers. And in this part, I'm going to look in the built-in stuff. And during the session, we'll also look into another way of analyzing performance, which is even more useful than what's built in. Now, we'll look into some resource dictionary strategies. It's a very small part, but it's pretty important because doing this wrongly can definitely have quite an impact on performance, specifically starter performance. After that, it's probably the most interesting part of the talk and the longest. It's UI virtualization, data virtualization, and a new feature in Windows Store F8.1, incremental data templates. If you do UI virtualization right and data virtualization right, well, then you have huge performance wins. So those are pretty important. And then I'd like to end with one slide and one demo. On task, stress, and offloading, mainly the number one mistake we see people make that can have a dramatic impact on performance, a dramatic negative impact on performance, even. But let's start with that architecture stuff, right? Just going to put the slide on screen. That's a bit easier to explain. So first of all, the architecture by default is multi-treaded. So XAML and the underlying.NET framework you use, or WinRT in this case, which has really very little to do with the.NET framework, is multi-treaded by default. So you don't have to do anything for this. If you have multiple cores, the XAML framework will automatically distribute work across those. Nothing needed there, but it's interesting to know, right? And then you see three types of threads on screen here, the UI thread, the composition thread, and the worker threads. The worker threads are the easiest. That's the stuff we do ourselves, so at least if we offload it to another thread. So our user code, if we offload it to the background, and application code, if it's offloaded to the background, runs on separate worker threads. The UI thread and the composition thread, on the other hand, those are there all the time. And the responsibilities immediately give away what we need to take care of and think of performance. So they run in sync, and the UI thread is the most heavy one. It's responsible at first for parsing all your XAML. So that's quite heavy stuff. It needs to parse those files. It's also responsible for taking those XAML elements, having a layout pass run on them, and then rendering them to visual primitives, let's say. And it then hands over those visual primitives to the composition thread, and the main responsibility of the composition thread is sending drawing commands to your hardware to draw those things on screen. So the UI thread actually parses and renders everything, and that's quite heavy. And then it hands it off to the composition thread, and that just composes the scene and sends it to the hardware. So far, so good. That's still not too heavy. But if you go and look into what other responsibilities the UI thread has, then you can immediately see that there can be some problems with that. Because the other responsibilities of the UI thread are handling events, so button click events handled by the UI thread. But also, by default, all your user code and all application code actually runs on your UI thread, unless you do something about it. So if you have a button click and you write code in there, that's actually running on your UI thread. If you write very heavy algorithm, some calculations in there, it's running on your UI thread. All application code as well. This may sound a bit weird, but I actually have some proof of that near the end of the session. So in fact, the thing we want to do is offload this UI thread as much as possible. And you can do that in two ways, either by ensuring code runs on the composition thread, which is pretty lightweight. There's room enough there, typically. Or by ensuring it runs into another thread, one of those worker threads. Now, how can you do that? How can you offload stuff from the UI thread to your composition thread? You can't just say, hey, CPU, run this on the composition thread. You can't do that. What you can do is organize your example in such a way that it automatically runs on the composition thread. And one of the ways of doing that is using dependent instead of independent animations. That's a huge win. An independent animation is an animation that has no impact on other objects in the scene. A dependent animation is one that when you animate a button, for example, that can have an impact on the position of other stuff on the same page. That automatically gets handed over to the composition thread. And the composition thread also takes care of scrolling and panning. So it does that by default. But all the other stuff is up to us. And that's what this session is about, really. It's all about offloading stuff from your UI thread, both UI virtualization, data virtualization, almost everything. So with that in the back of our heads, we can start with a few sample tips and tricks. First thing, you should always optimize your element count. If you look at something like this, this code will result in a black screen, a grid and a rectangle filled color black. But these are two elements. We've now created a grid in memory and a rectangle in memory. This is a better way of writing this. It's exactly the same result, but you only have one element in men. Now, it's a very small impact, but imagine this stuff like this in a grid view data template with tens of thousands of items. Well, you can see how this can start piling up. Another one is the same type of stuff, so getting your memory load as low as possible. To brush this, you define as a static resource. They are created once and reused. On the other end, if you define a brush at property level, it isn't reused. It's created every time over and over again. So if you look at code like this, we have a text box here. Foreground color is the same as that button's foreground color. That actually results in two brushes being created in memory, so two solid color brush instances. While on the other hand, if you define that brush as a static resource in your research dictionary and then reference it like this, there's only one instance of that. So that helps keep memory usage low as well. Now, I'm talking about memory usage. You should always try and keep it in the back of your head that you're not working, you're not designing and creating an app for a machine like this. This is a developer machine. All your machines are developer machines. But we're creating applications that should run smoothly on very low end, and that's typically ARM, very low-end ARM devices. They don't have the memory we have. They don't have the GPUs we have. That's what we always need to keep in the back of our heads. And while on that subject, there's one thing that's really important there, and that's this one. We should always minimize redrawing. And what that means is if I write code like this, I have a grid with two rows, background black, and on the second row, we have white with opacity 0.5. So this will result in a screen that's half black, half see-through white, something like that. What happens when this is sent to the composition thread and then to the drawing hardware is that first, the complete screen is drawn in black, and then it's overdrawn half of it in gray. This will be then. The problem is that it's drawing two pixels in the same place. If you do it like this, we don't have that anymore. We're not drawing two pixels in the same place anymore. And why is this so important? Well, a low-end ARM device can take about four pixels in the same place before starting to stutter. And four pixels in the same place, it's really not a lot. That's an app with a background on that grid view with some items with their own background. That's two pixels. On top of that, an image maybe, that's three pixels. And maybe you want some text on top of that. That's four pixels already. So this actually trumps everything. If you need to choose between creating more elements, like in this case, two rectangles, which kind of goes against what I said in the beginning, or overdrawing, then you should always choose for this. And I'm immediately going to show you the impact of it as well. So that's the most important one, because low-end device is not very good at handling overdraw. So how can we measure this then? Well, there's two things that are built into the framework that we can use. The first one is the frame rate counter. So we can just use debug settings on an able frame rate counter, typically in your app startup. And then you get something like this, on the left of your screen, on the right of your screen. And what do these numbers mean? I'm just going to put it all on screen. There we go. So the first one tells me what my UI thread frame rate is. And the second one tells me the CPU usage that's used per frame on the UI thread. The two last numbers, that's composition engine, system wide, by the way, and composition engine CPU usage. If you look at this, what would you want to use most? Because it's a bit counter-intuitive. Probably, you'd say, the app frames per second. Everything on my UI thread. I want to look at what's going on on my UI thread. Well, the thing is, if something's wrong on your UI threads, you are probably having problems with not offloading stuff to the background through tasks or not using UI virtualization. And those two topics will come after this. And there are better ways to analyze that, which I'll also show. So what I tend to use this for is to look at overdraw, to look at how heavy my composition engine is being hit. So I tend to look at the fourth one on screen. The next thing you can use also for overdraw is overdraw heatmap. This is the app we will use throughout the demos. It's a list of recipes. And if you enable the overdraw heatmap, you actually get something like this. The darker this is, the lighter this is, the more pixels are drawn in the same place. So now, let me show you what the effect of that overdraw can be. I'm just going to, this is, wait, you don't see it yet. Let's try it like that. That's better. OK, so I have, let me go down. OK. Can everyone read that like this? So this is a grid view. And the grid view is bound to a list of recipes. And it, of course, has an item template, this one, regular recipe template, to show me, as you can see here, those recipes. Now, I'm first going to show this to you with a very bad data template. So let me just uncomment that and comment the good one out. I'm actually doing everything wrong here. Because I am not reusing my brushes, as you can see. So this brush and this brush should always be the same static resource. I am over drawing way too much. My grid's background on top of that's a border with inside a border rectangle that's overdrawn, overdrawn, overdrawn, et cetera, et cetera, et cetera. So I'm actually going against everything I just said. Now, let's see what this gives. I already put the frame rate counters on when I run it. Gracewood's building. There we go. Look at the number at the top right of your screen. So I'm scrolling. It's around six. That's five, six, something like that. That's not much. It's very smooth on my PC. Now let's have a look at the other data template. So that's the composition engine that's in place here. So I can really use that for over drawing and the effect of it, because each pixel that has to be drawn is sent to the composition engine and then to the hardware. This is a better template. It results in mostly the same, but there's less overdraw. There's a lot less elements there. I'm using resources, static resource. Now let's have a look at the effect. And I'm going to scroll again. Now it's around four all the time. So what we had previously was around six, I guess. Now around four. You don't see the difference on my machine. But what this means is that by simply ensuring that my XAML is written in a way that takes into account the overdraw and the element count, I've actually reached a 50% speed increase or a 50% less load on my composition thread. That's actually a huge improvement simply by looking at your XAML code. And as said, this is a development machine. I can't just make it slower, although I always on fast machines anyway. I can't just make it slower. But do this on an ARM tablet and you'll start noticing the difference. OK, so that's the impact of writing your XAML correctly. Now let me start this up again. When talking about XAML and how it's structured, there's a few things that aren't so obvious that you should also take into account. And the first one is that one of the things that can lead to huge improvements is the fact that control has a default style. But more often than not, you're not using everything in that control. If you look at the template of a control, say, a GridView item, or any control, actually, you'll see it has a visual state manager to go from normal state to hover state to checked state, et cetera, et cetera, et cetera. All those states contain elements. And all those elements are created when an instance of that button, for example, is created. Even though you might never use the checked state or the hover state or et cetera, et cetera. If you don't use it, throw it out. Because it's all elements that have to be created. And even then, if you do want to use all the states, well, the default states aren't always that very optimized. So it's always a good idea to look at the default templates and remove what you don't need. One good thing, though, this was very important in Windows Store apps, Windows 8. Windows 8.1, Microsoft got pretty smart. They noticed some problems with ListViews and GridViews. And they actually improved performance of it through this here. Instead of, first of all, they optimized the default templates for those items. And second of all, and that's very smarting, they created separate presenters. So if you don't have to do anything for this, if you use a GridView now, there's a GridView item or ListView item presenter. And what that will do is, instead of creating all the states at once for each item, it will only create those states at the moment the user actually uses them. So that's a pretty smart thing of them to do. And it helped performance tremendously. Regardless of that, still a good idea to look into the different templates. We'll also look at some of the impacts of the GridView and templates later on, especially during the UI virtualization stuff. OK, so then we have two resource dictionary strategies. And this is also interesting to know. Everything you put in a resource dictionary is parsed at the moment that resource dictionary is referenced. So what we see a lot is that people think, OK, great. I'm going to put my resources in a resource dictionary. Not on that page. That's not very nicely ordered. No, I'm going to put in a resource dictionary. You end up with a huge resource dictionary. And that resource dictionary is then referenced in your app.sample. That means that when your application starts, the full resource dictionary has to be parsed. And as you probably know, a resource dictionary can grow to a huge amount of resources after a while. But that really doesn't make sense to do it like this. This really hurts startup performance. Why would you parse all the resources, even though some of those resources might only be used on one page or on two or three pages? So the general idea is to resource dictionary your reference in your app.sample should only contain application-wide resources, like brushes that are used throughout the app. It should never contain stuff like data templates that's only used on one page or on a few pages. For that, you can either use the pages resource dictionary, so page.resources. That's made for that. Or you can use a resource dictionary that you only import on the pages that actually use those resources. Just don't put them in one huge resource dictionary, because it will definitely hurt startup performance. There is a trade-off, however. If you don't cache your page, the resources that you put on page level will have to be parsed every time the user goes to that page again. So this is not something I can say as a general rule. It's something that you'll have to look into on a page per page, pages, pages, or application per application basis. What I tend to do is ensure my pages are cached, always. And I never put page resources in the application-wide resource dictionary. And that actually really helps, just because parsing is way too expensive and slows stuff down. OK, onto UI virtualization. What is UI virtualization? Well, imagine you have a huge list of recipes in my case. It's about 1,000, I think. And those recipes are already in memory. So we're talking about UI here, not about data. That's what's coming up next. So 1,000 recipes, recipe objects in memory. If you don't have UI virtualization and you bind that list of 1,000 recipes to your grid view, all those thousands item containers with all their images and all their overlays, et cetera, will be created, even though there might be only 20 on screen at the time. That has a huge impact. All those containers have to be created. Everything has to be parsed. Everything has to be rendered, layout, passes, all on your UI thread. It will be slow. UI virtualization, however, ensures that while the data is still in memory, of course, the item containers will only be created once the item is almost ready to be shown on screen. So instead of 1,000 recipes over recipe item containers, I'll have about 50 or 60. So it does some prefetching and stuff like that. But it won't be 1,000, it'll be 50 or 60. This is a huge performance win, by the way. Now, how do you get it? Well, that's the great news. If you don't do anything wrong, you get it out of the box. So every item control that derives from items control, like a list view, grid view, and even your own custom item controls, they support UI virtualization out of the box. So that's pretty great, right? Well, the problem is that there's quite a few things that can disable UI virtualization, if you're not careful. One of those things, the items panel. A grid view or a list view has a default items panel. Since Windows Store Apps 8.1, it's the item wrap grid by default. That supports UI virtualization. But if you change that panel, you must ensure you change it to one that still supports UI virtualization, because, for example, a stack panel or a variable-sized wrap grid, those don't support UI virtualization anymore. So if you use a variable-sized wrap grid, no UI virtualization. And there's actually nothing to be done about that currently. Another thing that disables UI virtualization, or rather, it used to disable it, was grouping. Once you start working with group data in Windows Store Apps, what happened then was that the groups were virtualized, but the data inside of the groups wasn't. So imagine you have 1,000 recipes, and you divide them into three groups. What used to happen was group one would be complete. All the items in group one would have to be rendered, while group two and three maybe not. But all the items in group one, which maybe 300, would have to be rendered, because virtualization was on the group level. Windows 8.1 solved that. So now it's on items level, so you don't have to be afraid to use grouping anymore. Another thing that, well, of course, you do need to use the item wrap grids or item stack panel. That's two panels who support that with grouping. Another thing that destroys UI virtualization are data template selectors. So once you use a data template selector, no UI virtualization anymore. Instead of data template selectors, it's not really good class design. But something, if performance really is a problem and you do need different data templates, what I see happening from time to time is one data template that actually contains two grids, and the underlying class contains a type property, and you bind the grid you want to see to the specific type of data in your class. It's not great, but it often helps performance if you do need different data templates. Now there's one more thing that's probably the most hard to fix or find out. But I'm first going to show a demo of this, because when we talk about UI virtualization, you probably want to know how you can see if it's virtualized or not, right? Because I said you can try and see, whoa, this is too slow. Maybe it's not virtualized, but that's not really correct. So let's try that. Now you do that. Well, you actually need a memory profiler for that. The thing is what we're going to do is we're going to check how many of those grid view items, let's say, are created in memory, and by analyzing our memory, we can then see, whoa, wait, this is about 1,000. That means UI virtualization isn't done. It's about the same as my amount of recipes. That can't be good. If it's a lot lower, you can say, OK, well, now I have UI virtualization. So I'm going to start by using a panel that disables UI virtualization. As I said, variable size to wrap grid does that. There we go. And I'm going to start a memory profiler. Now I tend to use the Telerik tools. This is memory profiling from Telerik. But there's actually lots and lots of different vendors who all have their own tools. I used JetBrains once. There's others as well. They're all more or less the same, so it's really up to your own preference. I just like this one. But even if you want to use another tool or another vendor's memory profiler, well, the end result is the same. What you need to look at is the same. So let me start that up. There we go. So I'm just going to let this start, and I'm not going to scroll or anything. So you might have already noticed that this was a little bit slower than in the beginning. The images appeared a bit slower. So you could already start guessing that something's wrong, but well, it's better to really see it in memory. So these are my recipes, like about 10, 12 on screen. So let's say, including prefetching. I'm not sure how many we'll get, but we sure shouldn't get 1,000 of those. So I'm going to take a snapshot. And what you now want to look for is the type instances that are in memory. So let me make this a little bit bigger so I can look by type here. What I expect to find are about 1,000 recipe instances. That's normal. That's my data. Let me just order by instance. It's probably the easiest to see. And there's about 936 items in here. OK, that makes sense. Now, what do I need to look for now to see if this UI virtualization is on or not? And that's where it starts to get a little bit annoying. Because in Windows 8 apps, Windows Store 8, this was very easy, you just look for the GridView items. Because each item in that GridView, well, there's a GridView item instance. When I started preparing this demo for a Windows Store 8.1 apps, I was amazed. Well, wait, where are my GridView items? Then I started thinking about what I just said before. So Microsoft really improved GridView performance by using a GridView item presenter, which is responsible for generating GridView items. So you're not going to find GridView items in memory anymore. Instead, you need to go and look for something else, something that is created, something an instance of is created for each recipe. And in this case, you can actually see these three lines here. If you go and look at the source code, with a bit of reflection of a GridView items presenter, you can see that it actually uses these dictionaries to keep references to what it has to create. So by looking at these three, you can start to analyze whether or not UI virtualization is on or not. If this is about the same as the items in your data collection, which in this case is the case, well, then you can be sure there's no UI virtualization. They should be a lot lower. There's about one default and then one for each GridView item container. So now we have a 937, so that's definitely no UI virtualization. Now let me start by changing this to a grid that is supportive of to a panel that does support virtualization. Items, grids, items, wrap grids, that was it. OK, so here we are again. Now let me just do that again. If you look at how fast it will appear, how fast recipes will appear, it should become obvious that we now have UI virtualization. That was already a bit faster. If I now go look at exactly the same, so let me get a snapshot. That snapshot takes a memory snapshot. It dumps everything that's in memory at that certain time to the Telerik Just trace so that it can analyze the memory. You can take different snapshots at different times as well if you want to look at what happens at that time and that time and compare them. So it's actually a memory dump. And again, I look at types, look at the instances. Let's see, 936 recipe instances. That's correct. That's my data. If I look at the same as I used to look at before, well, we see we now have about 63. So no longer are those created for everything that's not on screen. It's only created for what's on screen and some prefetching. So now we actually have UI virtualization. So that's a way of analyzing this. It's really all about memory analyzation. Now I said there was one more thing that can destroy UI virtualization, pretty important one as well. And that's the parent container. So for that, we need to know what the viewport is. And a viewport, well, that's the area of an items control that displays content. So in fact, in our case, what's on screen? Put it easy. When you have UI virtualization, what actually happens is that only the items close to that viewport will have their containers created. The problem is, if you put your items control, your grid view, in a parent that does not restrict viewport, well, then you won't have UI virtualization at all. So UI virtualization is only enabled when the parent container restricts the viewport. Now what restricts the viewport? A grid. A grid restricts the viewport. You can give it a height or a width. But even if this is your outer grid, so the root visual of your application, then it will have a height and a width of your screen. So it's still restricted. That's OK. This will have UI virtualization. So that'll look like that. However, some parents disable UI virtualization. And one of those is a canvas. So if you put your grid view in a canvas, you won't have UI virtualization unless you specifically restrict the grid view itself. So restricting the width of the surrounding canvas or the surrounding parent does not have an effect. You must restrict the width of the items control bound to the list you want to see virtualized. I'm going to show you this. Let me just see like that. So what I'm going to do now is I'm just going to put that same grid view in a canvas. There we go. And let me just comment this out. So I have a grid view here. Even though the canvas has a set width and height, the grid view hasn't. ItemSrapgage, for sure, the UI virtualization. Let me start that up. And if everything goes as planned, this won't look good because it's in a canvas, so it's going to go down. So let's just go ahead and do that. And let's just go ahead and do that. And let's just go ahead and do that. And let's just go ahead and do that. And let's just go ahead and do that. So I'm just going to put that in a virtualized mode because it's in a canvas, so it's going to go down. There we go. You see it's slow already. And if I now take another snapshot, let's take one. And I'm just going to do exactly the same as I did before. And there we go, again, the same high amount we really don't need. So UI virtualization is disabled. I can enable that again by setting a fixed width and height on the grid view. Now you might think who, in some good sense, is going to put the grid view in a canvas, right? The problem is there's another one, another control that disables it, that doesn't restrict the viewport, and that's a scroll viewer. So if you have your grid view in a scroll viewer, no UI virtualization. And it goes even further than that because often you are making pages that are then shown somewhere on another page. Well, the parent just goes up and up. So if somewhere on that other page there's a scroll viewer and inside that scroll viewer the width isn't restricted on the grid view, you will not have UI virtualization. So the importance of the parent container, that's one of the main mistakes we see made that disables UI virtualization. OK, so after UI virtualization, there's data virtualization. And when we talk about data virtualization, it's actually paging. That's the nice, the nice way to put it. So instead of working with that list of 1,000 recipes, or 936 apparently, we only work with a subset of the data instead of all the data. So we're going to go and load the data on demand. If you combine this with UI virtualization, well, that's pretty much huge performance win. There's two types of data virtualization supported by Windows Store apps. One is random access virtualization, and the other one is incremental virtualization. And we're going to look into both. First, on random access virtualization, what this means is this is used when you know the amount of, and I'm just going to say recipes, because that's what we'll keep on using. If you know the amount of recipes that will be in your collection beforehand, but you do not want to load all of them at once. So you know there'll be about 1,000 recipes, but you only want to load, let's say, 20 recipes when the user scrolls to a specific position. So when the user scrolls to position 20, recipe 20 to 40 is loaded. When we scroll to position 100, 100, 200, 20 is loaded. This is just only applicable for cases where you know the amount of items you will have in advance. And to do that, and to do any kind of data virtualization, actually, you're going to have to make your own collection type. What does this mean? Well, for random data access virtualization, you just need to implement iNotify collection, property collection changed. I notify collection changed, and I notify property changed. Your collection is then responsible for fetching the data async. And the general idea is, when the data hasn't been fetched, you just return null, which will then show the place holder. When the data must be fetched, you will load it async. You will put it in the collection's internal collection, and you will notify the UI that a certain element at a certain position has been replaced. And I'm going to show you how it looks and how to do it. So back to our solution. This just keeps on switching between duplicate and extend. So I have to switch as well. OK, so I turned off the memory profiler. That's good. And first, I'm going to show you what it looks like. Just create a list with the same recipe over and over and over again. Now, of course, the thing to know is I'm doing this from my PC, so I kind of faked a little delay so you could see what's going on. This one was the previous one. I think it's this. Noop. This. So I have a list here. Lots of times the same recipe. As you can see below here, scroll bar, it already knows that there are more. Define I go, say, a bit further. You can see there's no recipes there yet. And they are fetched on demand. So I scrolled somewhere. Nothing there. Those are all the placeholders, the gray stuff. And then somehow they get fetched and they get shown. That's what random data access virtualization is. Now let's look at how we do that. Well, actually, it's just a grid view bound to a recipe collection. But I'm going to show you the collection it's bound to. It's a collection I named random access virtualization recipe collection. Now let's look at how we implement that. I just implemented the I list interface and I notify collection changed. Now there's a lot of plumbing going on here. But I'm going to focus on the important part. I do put the code on my block later on. So you'll have it anyway. How does it know what to fetch and how do we fetch it? Those are two important parts. Well, if you bind a list, any list, actually, to a grid view, it's going to load items. It's going to, when you scroll to a certain position, it's going to trigger the indexer. So that's what we get out of the box. That means we get this. This is the indexer. And it passes in the position it needs to get. If you bind this to a list that's fully loaded, well, the indexer will just get the correct item out of the internal collection and show it. In our case, we don't have that yet because it's all annual out first. So we need to fetch it. That means that in the getter, we need to, and I'm just going to focus on the important parts here, we need to start loading the items. There's a bit of plumbing in here that ensures the items aren't loaded too much. The important part here is that the first thing we do is ensure we return NULL, which shows the placeholder. And as this is async, so NULL is returned before this is done. So the placeholder is shown. And then we load a bunch of items. And the important part is here again. That's it. So we run through, and again, this is plumbing, so I can load 20 items at the same time. I fake some delay because this will typically go to your back end. I get back the recipe I need. And I put it in the internal dictionary. So now my I list implementations internal dictionary contains that item, so next time it's fetched, it will automatically get that out of the internal dictionary. And then the last thing I need to do is raise property changed on that item. And that's then what happens here. It's a simple notify collection changed. It says that item has been replaced. And that's actually all there is to it. If you look at it, it's not a lot of code. A lot of this is plumbing, just to ensure I have a stack that not too much is done over and over and over again. For the rest, there's not that much to it. So it's really pretty easy to get something like this. And this is pretty powerful even. But there's another one that might be more suited, depending on your scenario. And that's incremental virtualization. Random access virtualization was I know the amount of items I have, and I want to load them on demand. Incremental virtualization means I don't know the amount of items I'll have. But when the user scrolls to the end of my grid view, I want to load the rest of the items. And how you do that is by having a collection that implements I support incremental loading. So that's the interface you need to implement. So typically, you just create a collection that inherits observable collection and implement that interface. So let's look at that. I'm going to show you what it looks like first. I still have that open here. Yep. I think it's this one. No. I have too many demos here. This is an incremental load. This is a collection that's implemented I support incremental loading. And look at below here. Apparently, about 20 items have been loaded. But when I start scrolling, it's automatically starting to load more, showing them on screen. My collection gets bigger, and so on, and so on, and so on. This actually just calls the Flickr API, and I look for food or something. So let's look at that. Again, oh, we're still there. Great. So not much to see there. The ViewModel just contains a recipe collection. This time, I named Flickr Collection with incremental load support. Some plumbing here as well. So I actually have, where is it? A lot of this stuff is just to ensure I can call the back end Flickr API. So I create a photo data common class which holds the data I get back from Flickr API, just a title, owner, description, image, et cetera, et cetera. And then I have my collection. So it should implement this interface. And if I look at what this interface has, well, it's not that much. One, has more items. And two, an operation that is triggered when I reach the end of my screen by scrolling. OK. Has more items. Kind of depends on what you're doing. But in this case, I'm calling Flickr API and I'm assuming there's going to be lots and lots of items. So just for demo purposes, I return true on HasMoreItems. Important thing here is load more items async part. I need some, I somehow needed to return an IAsync operation. And I also know that I want to run this in the background. And I also know that running stuff in the background is with a task. And I somehow need to cast that task to the IAsync operation. And it needs to have a generically typed load more items result in it. So that's a lot of stuff, actually. The good thing is you can easily cast a task, which is this, to an async operation, just calling.saasync operation. Easy as that. That's good enough. And then I still need to know what this load more items result must contain. And actually, that's just a helper class that contains the current count. So that's easy as well. Then there's the loading. And what I do is I start a new task. And I pass in, oh, I'm still running. I'm not going to do that. I pass in an async method to actually load, called the Flickr API. The Flickr API is called in this getPage method. This is just a REST call, as you can see, which generally turns me a list of photos. So I have these photos in this result. What do I need to do then? I need to add them to the collection. So that's this.add. And I have to do that through the dispatcher, because the adding to the collection has to be done on the UI thread. So I have to dispatch back to my UI thread. I'm specifically doing it like this. You don't have to do it like this with all this task, et cetera, et cetera. But if you don't do it like this, all the fetching and all the calculations will also run on your UI thread. And that's what we want to avoid. So that's why I'm starting a task here. I run the dispatcher. I add all the items to the internal collection. I increase the current page. It's just used for internal purposes. And I return the amount of items I got, because that's what's expected by my interface. And with that code, I'm actually done. This is all I need to do to get incremental load support. Now, there was something new introduced in Windows Store Apps 8.1. There we go again. And that was incremental data templates. So at the moment, we already know about UI virtualization and data virtualization. Well, here's a third thing that might help in some cases, some specific cases. And we're now talking about one recipe data template. So as you could see, those recipes are loaded at once. So data in there, the image is loaded, the image text is loaded, and then it's pushed to composition and shown. What incremental data templates do is they allow us to load a specific part of the template first and display that, and only afterwards display another part. So that could mean that I could already show all the text of the recipes, so the name of the recipe, and load the image afterwards. That can actually, it will never improve your performance. It will actually slow down your performance, but it will improve the perception of performance your user has, because you already see something on screen, and it doesn't have to wait for both the text and image to be loaded, you only have to wait for the text, and then the image will come afterwards. So this allows us to incrementally show elements from a data template instead of all at once. Now, do you do that? Well, there's new event. You handle the container content changing on ListView Base, and ListView Base is the base class for GridView and ListView. And from there, you just go and look at what you want to show first, and then pass that in, and then register a method for the second pass, register a method for the third pass, and so on and so on. There's quite a lot of code. I'm going to show you how it's done. Let me first show you what the effect is. If the internet is, if this is slow enough, it will work. It's not slow enough. I'm going to scroll, and if you look carefully, oh, screen gone. Duplicate. Ah, yeah, that's better. OK, so this is using incremental, the incremental collection from before, laid out a little bit differently, and data templates that are incremental as well. So if I go fast enough, you see it already. So first, the text is shown if text is available, and only afterwards, the image is loaded. So this does give you, user, the perception that it's going faster, which can definitely help. So we already see sparse of data. Now, how do you do that? This has to be done in code behind, by the way. I'm not a very big fan of it, but it does work. Sometimes for performance, you kind of have to throw out best practices as far as design patterns are concerned. So it's a bit of a trade-off. Let me show you that. That's not it. It's the third one, I think. This one. I, of course, have to find it. Oh, here we go. So first, the XAML code. It's actually very little to do with XAML. One thing you see here, my grid view with recipes, it has the container content changing event handled in code behind. What happens then? That's what I do. So I get, in this content container changing, it will be triggered. This is the first pass, so it should be no. What I have to do then is I have to look at the arguments which contain the item container, and that item container in turn contains the template route. So I actually have to go and traverse that to get to, in this case, first-time, first-time, first-time, first-time, first-time, in this case, first-time, the text block that will show my recipe title. So that's the first thing I have to do, which is this code. So I try to find all the elements in my data template. The ones I want to show, I set to visible, the ones I don't want to show yet, opacity zero. And then I need to fill in the text of that title element, so that title text block. I always get the item passed in and the template itself. So I can do everything I need with this. So from the arguments item, I get the underlying data. From the arguments item container, I get the data template. So what I do then is I set the title's text to the title from the data. And then I need to register an update callback, which is the method that will be triggered after this method is done. So the second time, the second pass is used for loading the image. And then I'm in the show recipe image method, which again gets these content content, container content changing event arguments. I find the picture in this case, that's the name I gave to the image. I set it to visible and I set the source. That's how you do this. Now you can immediately see this actually breaks data binding. It's an anti data binding pattern. So should we use it? Yes and no. It depends on what you think is more important. But for some cases, it does make sense. I mean, for the end user, it probably makes sense. If you're an architect or a project leads, it probably doesn't make as much sense. So it kind of depends. Okay, so the last thing I want to show you is this one. I'm not going to show the slide again because I have to be in code anyway. That's the most important thing to one common mistake that's made often. Using async wait will not offload to a background thread. Never, ever. That's a very important mistake that's often made. We often think that, okay, well, I'm going to use async on my methods and in that method, I'm going to use await. So this will run on a background thread. Well, that's not true. If you don't do anything specifically, it will run on your UI thread. So the only thing the async keyword does is state, okay, this method can contain an await statement. And the only thing the await statement does is, okay, run this code and return once it's completed. But if in the code that you're awaiting, you're not offloading anything to the background, then that will still run on the same thread you call it from, which is the UI thread. Then the next question is, why does this work for all those built-in API methods? Because if you await a file system not open, well, it will run in the background. Well, that is because internally, Microsoft always starts up tasks. They start up new tasks, and if you start new tasks, that will run in the background. So I'm going to show you this because this is how, this is probably next to UI and data virtualization, the most important thing you can do to offload stuff from your UI thread. And I'm just going to show you first how to not do it and what the effect is. I have a method here. Async returns a task, but in that method, there's actually nothing offloaded to the background at all. So I could, if I use a task that run in here, this will be in the background, but this time, not doing it. I'm just writing out stuff to my output window. And I do that once I click an item in my grid view. So let's see the effect of this. You'll probably know what's coming. It's going to go bad. Okay, that's the second screen, I think. Okay, so I can nicely scroll, and I click, and you'll have to believe me now. I'm scrolling, but this doesn't work anymore. My UI hangs, and why is my UI hanging? Because this code that's putting all this in my console window is now running on my UI threads, even though I'm using Async, await, et cetera, et cetera, et cetera. So how do you solve this then? It's simple. You have to, for your own code, your user code, you have to manually start task to ensure it's scheduled on the background and no longer on your UI thread. So it's actually pretty easy. You can either do that in this method, or you can do that here. And let me start that up again. And if I now go and do the same thing, once it's loaded, there we go. To it was, I think, runs. I click, and I can still nicely scroll, even though it's outputting those same numbers. So that's how you offload stuff from your UI thread. And it actually also proves that unless you do something about it, button click actually does run on your UI. OK. So that was actually, except for the hidden slides, which I didn't want to show anyway. That's actually the last thing I wanted to show you. Right on time, I guess. Now, is there more to be said about performance? Yes, of course there is. You might wonder why I'm not using a performance profile, but only a memory profile. Well, performance profiling is something you typically do to profile how long a specific method takes, something like that, while when you're working with XAML apps, your problems typically don't stem from that. They stem from bad UI virtualization, bad data virtualization. There's a lot of stuff to be said on working with animations, dependent or independent. There's a lot of best practices on working with media, the file system, application lifecycle is not one of those. It's too much to put in one hour. So I kind of picked out the ones that most mistakes are made against. If you want to know more about this, I'm going to put all these on my blog within a few hours. And there's actually a plural site course I made on Windows for app performance as well. And I think if the guys are still there, they'll give you a free voucher for the plural site course. So that's about all I had to say. If there are any questions, feel free to ask them. No? Okay, so I thank you to stay till the end of the conference, in the end of my session, and I hope it was useful. Thanks. Thank you.
 Test. Okay. Everyone can hear me, I guess? Okay.  Our last session of the last day of great conference.  So I'm very glad some people decided to stay until the end.  And I hope I'll make it to a while.  I'm going to start by introducing myself.  My name is Kevin.  I'm a solution architect, mainly focusing on mobile  applications.  I've been at the same company, Real Dolman, Belgium company,  for about 10 years.  So the things I'm currently doing, it's mainly back-end stuff.  So mainly architecture stuff.  So we can make applications cross-platform for mobile  clients.  One of those mobile clients we tend to make is a Windows Store  app or a Windows Phone app even.  And when you think about Windows Phone app,  Windows Store app, that's XAML in my case,  then what we often see are problems with performance,  even now.  So that's what this session is about.  It's really about tips and tricks to make your app  perform great.  If you want to reach me afterwards,  my email address is on there.  That's my personal email address.  But the easiest by far is Twitter.  So that's the easiest way to reach me.  Okay.  So let's have a look at what we're going to look at today.  I'm going to start with a XAML architecture overview,  because it's quite important to know what's going on behind  the scenes so we can understand what we need to do to get  our app performing well.  So that's the first thing.  And then we're going to dive right into some XAML  performance tips and tricks.  By this, I mean these are the tips and tricks on how to  organize your XAML, how to write the XAML elements to  ensure that performance is great, and what writing them  wrongly can have as an impact.  Now, if you're talking about performance, we also need a way  to measure this.  And there's a few ways of analyzing performance.  It's mainly memory analyzing, by the way, not performance  profilers.  And in this part, I'm going to look in the built-in stuff.  And during the session, we'll also look into another way of  analyzing performance, which is even more useful than  what's built in.  Now, we'll look into some resource  dictionary strategies.  It's a very small part, but it's pretty important because  doing this wrongly can definitely have quite an impact  on performance, specifically starter performance.  After that, it's probably the most interesting part of the  talk and the longest.  It's UI virtualization, data virtualization, and a new  feature in Windows Store F8.1, incremental data templates.  If you do UI virtualization right and data virtualization  right, well, then you have huge performance wins.  So those are pretty important.  And then I'd like to end with one slide and one demo.  On task, stress, and offloading, mainly the number one  mistake we see people make that can have a dramatic impact  on performance, a dramatic negative impact on  performance, even.  But let's start with that architecture stuff, right?  Just going to put the slide on screen.  That's a bit easier to explain.  So first of all, the architecture by default  is multi-treaded.  So XAML and the underlying.NET framework you use, or  WinRT in this case, which has really very little to do with  the.NET framework, is multi-treaded by default.  So you don't have to do anything for this.  If you have multiple cores, the XAML framework will  automatically distribute work across those.  Nothing needed there, but it's interesting to know, right?  And then you see three types of threads on screen here, the  UI thread, the composition thread, and the worker threads.  The worker threads are the easiest.  That's the stuff we do ourselves, so at least if we  offload it to another thread.  So our user code, if we offload it to the background, and  application code, if it's offloaded to the background,  runs on separate worker threads.  The UI thread and the composition thread, on the  other hand, those are there all the time.  And the responsibilities immediately give away what we  need to take care of and think of performance.  So they run in sync, and the UI thread is the most heavy one.  It's responsible at first for parsing all your XAML.  So that's quite heavy stuff.  It needs to parse those files.  It's also responsible for taking those XAML elements,  having a layout pass run on them, and then rendering them  to visual primitives, let's say.  And it then hands over those visual primitives to the  composition thread, and the main responsibility of the  composition thread is sending drawing commands to your  hardware to draw those things on screen.  So the UI thread actually parses and renders everything,  and that's quite heavy.  And then it hands it off to the composition thread, and that  just composes the scene and sends it to the hardware.  So far, so good.  That's still not too heavy.  But if you go and look into what other responsibilities the  UI thread has, then you can immediately see that there can  be some problems with that.  Because the other responsibilities of the UI  thread are handling events, so button click events handled by  the UI thread.  But also, by default, all your user code and all  application code actually runs on your UI thread, unless  you do something about it.  So if you have a button click and you write code in there,  that's actually running on your UI thread.  If you write very heavy algorithm, some calculations  in there, it's running on your UI thread.  All application code as well.  This may sound a bit weird, but I actually have some proof  of that near the end of the session.  So in fact, the thing we want to do is offload this UI thread  as much as possible.  And you can do that in two ways, either by ensuring code  runs on the composition thread, which is pretty lightweight.  There's room enough there, typically.  Or by ensuring it runs into another thread, one of those  worker threads.  Now, how can you do that?  How can you offload stuff from the UI  thread to your composition thread?  You can't just say, hey, CPU, run this on the  composition thread.  You can't do that.  What you can do is organize your example in such a way that  it automatically runs on the composition thread.  And one of the ways of doing that is using dependent  instead of independent animations.  That's a huge win.  An independent animation is an animation that has no impact  on other objects in the scene.  A dependent animation is one that when you animate a button,  for example, that can have an impact on the position of  other stuff on the same page.  That automatically gets handed over to the composition  thread.  And the composition thread also takes care of scrolling and  panning.  So it does that by default.  But all the other stuff is up to us.  And that's what this session is about, really.  It's all about offloading stuff from your UI thread, both  UI virtualization, data virtualization, almost  everything.  So with that in the back of our heads, we can start with a  few sample tips and tricks.  First thing, you should always optimize your element count.  If you look at something like this, this code will result in  a black screen, a grid and a rectangle filled color black.  But these are two elements.  We've now created a grid in memory and a rectangle in  memory.  This is a better way of writing this.  It's exactly the same result, but you only have one element  in men.  Now, it's a very small impact, but imagine this stuff like  this in a grid view data template with tens of  thousands of items.  Well, you can see how this can start piling up.  Another one is the same type of stuff, so getting your memory  load as low as possible.  To brush this, you define as a static resource.  They are created once and reused.  On the other end, if you define a brush at property level, it  isn't reused.  It's created every time over and over again.  So if you look at code like this, we have a text box here.  Foreground color is the same as that button's foreground color.  That actually results in two brushes being created in memory,  so two solid color brush instances.  While on the other hand, if you define that brush as a  static resource in your research dictionary and then  reference it like this, there's only one instance of that.  So that helps keep memory usage low as well.  Now, I'm talking about memory usage.  You should always try and keep it in the back of your head  that you're not working, you're not designing and creating  an app for a machine like this.  This is a developer machine.  All your machines are developer machines.  But we're creating applications that should run  smoothly on very low end, and that's typically ARM, very  low-end ARM devices.  They don't have the memory we have.  They don't have the GPUs we have.  That's what we always need to keep in the back of our heads.  And while on that subject, there's one thing that's  really important there, and that's this one.  We should always minimize redrawing.  And what that means is if I write code like this, I have a  grid with two rows, background black, and on the second row,  we have white with opacity 0.5.  So this will result in a screen that's half black, half  see-through white, something like that.  What happens when this is sent to the composition thread and  then to the drawing hardware is that first, the complete  screen is drawn in black, and then it's overdrawn half of  it in gray.  This will be then.  The problem is that it's drawing two  pixels in the same place.  If you do it like this, we don't have that anymore.  We're not drawing two pixels in the same place anymore.  And why is this so important?  Well, a low-end ARM device can take about four pixels in  the same place before starting to stutter.  And four pixels in the same place, it's really not a lot.  That's an app with a background on that grid view with  some items with their own background.  That's two pixels.  On top of that, an image maybe, that's three pixels.  And maybe you want some text on top of that.  That's four pixels already.  So this actually trumps everything.  If you need to choose between creating more elements, like  in this case, two rectangles, which kind of goes against  what I said in the beginning, or overdrawing, then you  should always choose for this.  And I'm immediately going to show you the  impact of it as well.  So that's the most important one, because low-end device is  not very good at handling overdraw.  So how can we measure this then?  Well, there's two things that are built into the framework  that we can use.  The first one is the frame rate counter.  So we can just use debug settings on an able frame rate  counter, typically in your app startup.  And then you get something like this, on the left of your  screen, on the right of your screen.  And what do these numbers mean?  I'm just going to put it all on screen.  There we go.  So the first one tells me what my UI thread frame rate is.  And the second one tells me the CPU usage that's used per  frame on the UI thread.  The two last numbers, that's composition engine, system  wide, by the way, and composition engine CPU usage.  If you look at this, what would you want to use most?  Because it's a bit counter-intuitive.  Probably, you'd say, the app frames per second.  Everything on my UI thread.  I want to look at what's going on on my UI thread.  Well, the thing is, if something's wrong on your UI  threads, you are probably having problems with not  offloading stuff to the background through tasks or  not using UI virtualization.  And those two topics will come after this.  And there are better ways to analyze that, which I'll  also show.  So what I tend to use this for is to look at overdraw, to  look at how heavy my composition engine is being  hit.  So I tend to look at the fourth one on screen.  The next thing you can use also for overdraw is  overdraw heatmap.  This is the app we will use throughout the demos.  It's a list of recipes.  And if you enable the overdraw heatmap, you actually get  something like this.  The darker this is, the lighter this is, the more pixels  are drawn in the same place.  So now, let me show you what the effect of that  overdraw can be.  I'm just going to, this is, wait, you don't see it yet.  Let's try it like that.  That's better.  OK, so I have, let me go down.  OK.  Can everyone read that like this?  So this is a grid view.  And the grid view is bound to a list of recipes.  And it, of course, has an item template, this one,  regular recipe template, to show me, as you can see here,  those recipes.  Now, I'm first going to show this to you with a very bad  data template.  So let me just uncomment that and comment the good one out.  I'm actually doing everything wrong here.  Because I am not reusing my brushes, as you can see.  So this brush and this brush should always be the same  static resource.  I am over drawing way too much.  My grid's background on top of that's a border with inside  a border rectangle that's overdrawn, overdrawn,  overdrawn, et cetera, et cetera, et cetera.  So I'm actually going against everything I just said.  Now, let's see what this gives.  I already put the frame rate counters on when I run it.  Gracewood's building.  There we go.  Look at the number at the top right of your screen.  So I'm scrolling.  It's around six.  That's five, six, something like that.  That's not much.  It's very smooth on my PC.  Now let's have a look at the other data template.  So that's the composition engine that's in place here.  So I can really use that for over drawing and the effect of  it, because each pixel that has to be drawn is sent to the  composition engine and then to the hardware.  This is a better template.  It results in mostly the same, but there's less overdraw.  There's a lot less elements there.  I'm using resources, static resource.  Now let's have a look at the effect.  And I'm going to scroll again.  Now it's around four all the time.  So what we had previously was around six, I guess.  Now around four.  You don't see the difference on my machine.  But what this means is that by simply ensuring that my  XAML is written in a way that takes into account the  overdraw and the element count, I've actually reached a 50%  speed increase or a 50% less load on my composition thread.  That's actually a huge improvement simply by looking  at your XAML code.  And as said, this is a development machine.  I can't just make it slower, although I always on fast  machines anyway.  I can't just make it slower.  But do this on an ARM tablet and you'll start  noticing the difference.  OK, so that's the impact of writing your XAML correctly.  Now let me start this up again.  When talking about XAML and how it's structured, there's a  few things that aren't so obvious that you should also  take into account.  And the first one is that one of the things that can lead to  huge improvements is the fact that  control has a default style.  But more often than not, you're not using everything in  that control.  If you look at the template of a control, say, a GridView  item, or any control, actually, you'll see it has a  visual state manager to go from normal state to hover  state to checked state, et cetera, et cetera, et cetera.  All those states contain elements.  And all those elements are created when an instance of  that button, for example, is created.  Even though you might never use the checked state or the  hover state or et cetera, et cetera.  If you don't use it, throw it out.  Because it's all elements that have to be created.  And even then, if you do want to use all the states, well,  the default states aren't always that very optimized.  So it's always a good idea to look at the default  templates and remove what you don't need.  One good thing, though, this was very important in Windows  Store apps, Windows 8.  Windows 8.1, Microsoft got pretty smart.  They noticed some problems with ListViews and GridViews.  And they actually improved performance of it  through this here.  Instead of, first of all, they optimized the default  templates for those items.  And second of all, and that's very smarting, they created  separate presenters.  So if you don't have to do anything for this, if you use  a GridView now, there's a GridView item or ListView  item presenter.  And what that will do is, instead of creating all the  states at once for each item, it will only create those  states at the moment the user actually uses them.  So that's a pretty smart thing of them to do.  And it helped performance tremendously.  Regardless of that, still a good idea to look into the  different templates.  We'll also look at some of the impacts of the GridView and  templates later on, especially during the UI  virtualization stuff.  OK, so then we have two resource dictionary strategies.  And this is also interesting to know.  Everything you put in a resource dictionary is  parsed at the moment that resource dictionary is  referenced.  So what we see a lot is that people think, OK, great.  I'm going to put my resources in a resource dictionary.  Not on that page.  That's not very nicely ordered.  No, I'm going to put in a resource dictionary.  You end up with a huge resource dictionary.  And that resource dictionary is then referenced in your  app.sample.  That means that when your application starts, the full  resource dictionary has to be parsed.  And as you probably know, a resource dictionary can grow to  a huge amount of resources after a while.  But that really doesn't make sense to do it like this.  This really hurts startup performance.  Why would you parse all the resources, even though some of  those resources might only be used on one page or on two  or three pages?  So the general idea is to resource dictionary your  reference in your app.sample should only contain  application-wide resources, like brushes that are used  throughout the app.  It should never contain stuff like data templates that's  only used on one page or on a few pages.  For that, you can either use the pages resource  dictionary, so page.resources.  That's made for that.  Or you can use a resource dictionary that you only import  on the pages that actually use those resources.  Just don't put them in one huge resource dictionary, because  it will definitely hurt startup performance.  There is a trade-off, however.  If you don't cache your page, the resources that you put on  page level will have to be parsed every time the user goes  to that page again.  So this is not something I can say as a general rule.  It's something that you'll have to look into on a page per  page, pages, pages, or application per application basis.  What I tend to do is ensure my pages are cached, always.  And I never put page resources in the application-wide  resource dictionary.  And that actually really helps, just because parsing is way  too expensive and slows stuff down.  OK, onto UI virtualization.  What is UI virtualization?  Well, imagine you have a huge list of recipes in my case.  It's about 1,000, I think.  And those recipes are already in memory.  So we're talking about UI here, not about data.  That's what's coming up next.  So 1,000 recipes, recipe objects in memory.  If you don't have UI virtualization and you bind  that list of 1,000 recipes to your grid view, all those  thousands item containers with all their images and all  their overlays, et cetera, will be created, even though  there might be only 20 on screen at the time.  That has a huge impact.  All those containers have to be created.  Everything has to be parsed.  Everything has to be rendered, layout, passes, all on your  UI thread.  It will be slow.  UI virtualization, however, ensures that while the data  is still in memory, of course, the item containers will  only be created once the item is almost ready to be shown  on screen.  So instead of 1,000 recipes over recipe item containers, I'll  have about 50 or 60.  So it does some prefetching and stuff like that.  But it won't be 1,000, it'll be 50 or 60.  This is a huge performance win, by the way.  Now, how do you get it?  Well, that's the great news.  If you don't do anything wrong, you get it out of the box.  So every item control that derives from items control,  like a list view, grid view, and even your own custom item  controls, they support UI virtualization out of the  box.  So that's pretty great, right?  Well, the problem is that there's quite a few things  that can disable UI virtualization, if you're not  careful.  One of those things, the items panel.  A grid view or a list view has a default items panel.  Since Windows Store Apps 8.1, it's the item wrap grid by  default.  That supports UI virtualization.  But if you change that panel, you must ensure you change it  to one that still supports UI virtualization, because, for  example, a stack panel or a variable-sized wrap grid, those  don't support UI virtualization anymore.  So if you use a variable-sized wrap grid, no UI  virtualization.  And there's actually nothing to be done about that currently.  Another thing that disables UI virtualization, or rather, it  used to disable it, was grouping.  Once you start working with group data in Windows Store Apps,  what happened then was that the groups were virtualized, but  the data inside of the groups wasn't.  So imagine you have 1,000 recipes, and you divide them  into three groups.  What used to happen was group one would be complete.  All the items in group one would have to be rendered, while  group two and three maybe not.  But all the items in group one, which maybe 300, would have  to be rendered, because virtualization was on the group  level.  Windows 8.1 solved that.  So now it's on items level, so you don't have to be afraid  to use grouping anymore.  Another thing that, well, of course, you do need to use the  item wrap grids or item stack panel.  That's two panels who support that with grouping.  Another thing that destroys UI virtualization are data  template selectors.  So once you use a data template selector, no UI  virtualization anymore.  Instead of data template selectors, it's not really  good class design.  But something, if performance really is a problem and you  do need different data templates, what I see happening  from time to time is one data template that actually  contains two grids, and the underlying class contains a  type property, and you bind the grid you want to see to  the specific type of data in your class.  It's not great, but it often helps performance if you do  need different data templates.  Now there's one more thing that's probably the most  hard to fix or find out.  But I'm first going to show a demo of this, because when we  talk about UI virtualization, you probably want to know how  you can see if it's virtualized or not, right?  Because I said you can try and see, whoa, this is too slow.  Maybe it's not virtualized, but that's not really correct.  So let's try that.  Now you do that.  Well, you actually need a memory profiler for that.  The thing is what we're going to do is we're going to check  how many of those grid view items, let's say, are created in  memory, and by analyzing our memory, we can then see, whoa,  wait, this is about 1,000.  That means UI virtualization isn't done.  It's about the same as my amount of recipes.  That can't be good.  If it's a lot lower, you can say, OK, well, now I have UI  virtualization.  So I'm going to start by using a panel that disables UI  virtualization.  As I said, variable size to wrap grid does that.  There we go.  And I'm going to start a memory profiler.  Now I tend to use the Telerik tools.  This is memory profiling from Telerik.  But there's actually lots and lots of different vendors who  all have their own tools.  I used JetBrains once.  There's others as well.  They're all more or less the same, so it's really up to  your own preference.  I just like this one.  But even if you want to use another tool or another  vendor's memory profiler, well, the end result is the  same.  What you need to look at is the same.  So let me start that up.  There we go.  So I'm just going to let this start, and I'm not going to  scroll or anything.  So you might have already noticed that this was a little  bit slower than in the beginning.  The images appeared a bit slower.  So you could already start guessing that something's  wrong, but well, it's better to really see it in memory.  So these are my recipes, like about 10, 12 on screen.  So let's say, including prefetching.  I'm not sure how many we'll get, but we sure shouldn't get  1,000 of those.  So I'm going to take a snapshot.  And what you now want to look for is the type instances that  are in memory.  So let me make this a little bit bigger so I can look by  type here.  What I expect to find are about 1,000 recipe instances.  That's normal.  That's my data.  Let me just order by instance.  It's probably the easiest to see.  And there's about 936 items in here.  OK, that makes sense.  Now, what do I need to look for now to see if this UI  virtualization is on or not?  And that's where it starts to get a little bit annoying.  Because in Windows 8 apps, Windows Store 8, this was very  easy, you just look for the GridView items.  Because each item in that GridView, well, there's a  GridView item instance.  When I started preparing this demo for a Windows Store 8.1  apps, I was amazed.  Well, wait, where are my GridView items?  Then I started thinking about what I just said before.  So Microsoft really improved GridView performance by  using a GridView item presenter, which is responsible  for generating GridView items.  So you're not going to find GridView items in memory  anymore.  Instead, you need to go and look for something else,  something that is created, something an instance of is  created for each recipe.  And in this case, you can actually see these three  lines here.  If you go and look at the source code, with a bit of  reflection of a GridView items presenter, you can see that  it actually uses these dictionaries to keep references  to what it has to create.  So by looking at these three, you can start to analyze  whether or not UI virtualization is on or not.  If this is about the same as the items in your data  collection, which in this case is the case, well, then you  can be sure there's no UI virtualization.  They should be a lot lower.  There's about one default and then one for each  GridView item container.  So now we have a 937, so that's definitely no UI  virtualization.  Now let me start by changing this to a grid that is  supportive of to a panel that does support virtualization.  Items, grids, items, wrap grids, that was it.  OK, so here we are again.  Now let me just do that again.  If you look at how fast it will appear, how fast recipes  will appear, it should become obvious that we now have UI  virtualization.  That was already a bit faster.  If I now go look at exactly the same, so let me get a  snapshot.  That snapshot takes a memory snapshot.  It dumps everything that's in memory at that certain time to  the Telerik Just trace so that it can analyze the memory.  You can take different snapshots at different times as  well if you want to look at what happens at that time and  that time and compare them.  So it's actually a memory dump.  And again, I look at types, look at the instances.  Let's see, 936 recipe instances.  That's correct.  That's my data.  If I look at the same as I used to look at before, well, we  see we now have about 63.  So no longer are those created for everything that's not on  screen.  It's only created for what's on screen and some prefetching.  So now we actually have UI virtualization.  So that's a way of analyzing this.  It's really all about memory analyzation.  Now I said there was one more thing that can destroy UI  virtualization, pretty important one as well.  And that's the parent container.  So for that, we need to know what the viewport is.  And a viewport, well, that's the area of an items  control that displays content.  So in fact, in our case, what's on screen?  Put it easy.  When you have UI virtualization, what actually  happens is that only the items close to that viewport will  have their containers created.  The problem is, if you put your items control, your grid view,  in a parent that does not restrict viewport, well, then  you won't have UI virtualization at all.  So UI virtualization is only enabled when the parent  container restricts the viewport.  Now what restricts the viewport?  A grid.  A grid restricts the viewport.  You can give it a height or a width.  But even if this is your outer grid, so the root visual of  your application, then it will have a height and a width of  your screen.  So it's still restricted.  That's OK.  This will have UI virtualization.  So that'll look like that.  However, some parents disable UI virtualization.  And one of those is a canvas.  So if you put your grid view in a canvas, you won't have UI  virtualization unless you specifically restrict the grid  view itself.  So restricting the width of the surrounding canvas or the  surrounding parent does not have an effect.  You must restrict the width of the items control bound to  the list you want to see virtualized.  I'm going to show you this.  Let me just see like that.  So what I'm going to do now is I'm just going to put that  same grid view in a canvas.  There we go.  And let me just comment this out.  So I have a grid view here.  Even though the canvas has a set width and height, the grid  view hasn't.  ItemSrapgage, for sure, the UI virtualization.  Let me start that up.  And if everything goes as planned, this won't look good  because it's in a canvas, so it's going to go down.  So let's just go ahead and do that.  And let's just go ahead and do that.  And let's just go ahead and do that.  And let's just go ahead and do that.  And let's just go ahead and do that.  So I'm just going to put that in a  virtualized mode because it's in a canvas, so it's going to  go down.  There we go.  You see it's slow already.  And if I now take another snapshot, let's take one.  And I'm just going to do exactly the same as I did before.  And there we go, again, the same high amount we really don't  need.  So UI virtualization is disabled.  I can enable that again by setting a fixed width and height  on the grid view.  Now you might think who, in some good sense, is going to put  the grid view in a canvas, right?  The problem is there's another one, another control that  disables it, that doesn't restrict the viewport, and  that's a scroll viewer.  So if you have your grid view in a scroll viewer, no UI  virtualization.  And it goes even further than that because often you are  making pages that are then shown somewhere on another page.  Well, the parent just goes up and up.  So if somewhere on that other page there's a scroll viewer  and inside that scroll viewer the width isn't restricted on  the grid view, you will not have UI virtualization.  So the importance of the parent container, that's one of the  main mistakes we see made that disables UI virtualization.  OK, so after UI virtualization, there's data  virtualization.  And when we talk about data virtualization, it's actually  paging.  That's the nice, the nice way to put it.  So instead of working with that list of 1,000 recipes, or  936 apparently, we only work with  a subset of the data instead of all the data.  So we're going to go and load the data on demand.  If you combine this with UI virtualization, well, that's  pretty much huge performance win.  There's two types of data virtualization supported by  Windows Store apps.  One is random access virtualization, and the other  one is incremental virtualization.  And we're going to look into both.  First, on random access virtualization, what this means  is this is used when you know the amount of, and I'm just  going to say recipes, because that's what we'll keep on  using.  If you know the amount of recipes that will be in your  collection beforehand, but you do not want to load all of  them at once.  So you know there'll be about 1,000 recipes, but you only  want to load, let's say, 20 recipes when the user scrolls  to a specific position.  So when the user scrolls to position 20, recipe 20 to 40  is loaded.  When we scroll to position 100, 100,  200, 20 is loaded.  This is just only applicable for cases where you know the  amount of items you will have in advance.  And to do that, and to do any kind of data virtualization,  actually, you're going to have to make your own  collection type.  What does this mean?  Well, for random data access virtualization, you just need  to implement iNotify collection, property collection  changed.  I notify collection changed, and I notify property changed.  Your collection is then responsible for fetching the  data async.  And the general idea is, when the data hasn't been fetched,  you just return null, which will then show the place  holder.  When the data must be fetched, you will load it async.  You will put it in the collection's internal  collection, and you will notify the UI that a certain  element at a certain position has been replaced.  And I'm going to show you how it looks and how to do it.  So back to our solution.  This just keeps on switching between duplicate and  extend.  So I have to switch as well.  OK, so I turned off the memory profiler.  That's good.  And first, I'm going to show you what it looks like.  Just create a list with the same recipe over and over and  over again.  Now, of course, the thing to know is I'm doing this from  my PC, so I kind of faked a little delay so you could see  what's going on.  This one was the previous one.  I think it's this.  Noop.  This.  So I have a list here.  Lots of times the same recipe.  As you can see below here, scroll bar, it already knows  that there are more.  Define I go, say, a bit further.  You can see there's no recipes there yet.  And they are fetched on demand.  So I scrolled somewhere.  Nothing there.  Those are all the placeholders, the gray stuff.  And then somehow they get fetched and they get shown.  That's what random data access virtualization is.  Now let's look at how we do that.  Well, actually, it's just a grid view bound to a recipe  collection.  But I'm going to show you the collection it's bound to.  It's a collection I named random access virtualization  recipe collection.  Now let's look at how we implement that.  I just implemented the I list interface and I notify  collection changed.  Now there's a lot of plumbing going on here.  But I'm going to focus on the important part.  I do put the code on my block later on.  So you'll have it anyway.  How does it know what to fetch and how do we fetch it?  Those are two important parts.  Well, if you bind a list, any list, actually, to a grid  view, it's going to load items.  It's going to, when you scroll to a certain position, it's  going to trigger the indexer.  So that's what we get out of the box.  That means we get this.  This is the indexer.  And it passes in the position it needs to get.  If you bind this to a list that's fully loaded, well, the  indexer will just get the correct item out of the  internal collection and show it.  In our case, we don't have that yet because it's all  annual out first.  So we need to fetch it.  That means that in the getter, we need to, and I'm just  going to focus on the important parts here, we need to  start loading the items.  There's a bit of plumbing in here that ensures the items  aren't loaded too much.  The important part here is that the first thing we do is  ensure we return NULL, which shows the placeholder.  And as this is async, so NULL is returned  before this is done.  So the placeholder is shown.  And then we load a bunch of items.  And the important part is here again.  That's it.  So we run through, and again, this is plumbing, so I can  load 20 items at the same time.  I fake some delay because this will typically go to your  back end.  I get back the recipe I need.  And I put it in the internal dictionary.  So now my I list implementations internal dictionary  contains that item, so next time it's fetched, it will  automatically get that out of the internal dictionary.  And then the last thing I need to do is raise property  changed on that item.  And that's then what happens here.  It's a simple notify collection changed.  It says that item has been replaced.  And that's actually all there is to it.  If you look at it, it's not a lot of code.  A lot of this is plumbing, just to ensure I have a stack  that not too much is done over and over and over again.  For the rest, there's not that much to it.  So it's really pretty easy to get something like this.  And this is pretty powerful even.  But there's another one that might be more suited,  depending on your scenario.  And that's incremental virtualization.  Random access virtualization was I know the amount of items  I have, and I want to load them on demand.  Incremental virtualization means I don't know the amount of  items I'll have.  But when the user scrolls to the end of my grid view, I want  to load the rest of the items.  And how you do that is by having a collection that  implements I support incremental loading.  So that's the interface you need to implement.  So typically, you just create a collection that inherits  observable collection and implement that interface.  So let's look at that.  I'm going to show you what it looks like first.  I still have that open here.  Yep.  I think it's this one.  No.  I have too many demos here.  This is an incremental load.  This is a collection that's implemented I support  incremental loading.  And look at below here.  Apparently, about 20 items have been loaded.  But when I start scrolling, it's automatically starting to  load more, showing them on screen.  My collection gets bigger, and so on, and so on, and so on.  This actually just calls the Flickr API, and I look for  food or something.  So let's look at that.  Again, oh, we're still there.  Great.  So not much to see there.  The ViewModel just contains a recipe collection.  This time, I named Flickr Collection with  incremental load support.  Some plumbing here as well.  So I actually have, where is it?  A lot of this stuff is just to ensure I can call the back  end Flickr API.  So I create a photo data common class which holds the  data I get back from Flickr API, just a title, owner,  description, image, et cetera, et cetera.  And then I have my collection.  So it should implement this interface.  And if I look at what this interface has, well, it's not  that much.  One, has more items.  And two, an operation that is triggered when I reach the end  of my screen by scrolling.  OK.  Has more items.  Kind of depends on what you're doing.  But in this case, I'm calling Flickr API and I'm assuming  there's going to be lots and lots of items.  So just for demo purposes, I return true on HasMoreItems.  Important thing here is load more items async part.  I need some, I somehow needed to return an IAsync operation.  And I also know that I want to run this in the background.  And I also know that running stuff in the background is  with a task.  And I somehow need to cast that task to the IAsync operation.  And it needs to have a generically typed load more  items result in it.  So that's a lot of stuff, actually.  The good thing is you can easily cast a task, which is  this, to an async operation, just calling.saasync  operation.  Easy as that.  That's good enough.  And then I still need to know what this load more items  result must contain.  And actually, that's just a helper class that contains the  current count.  So that's easy as well.  Then there's the loading.  And what I do is I start a new task.  And I pass in, oh, I'm still running.  I'm not going to do that.  I pass in an async method to actually load,  called the Flickr API.  The Flickr API is called in this getPage method.  This is just a REST call, as you can see, which generally  turns me a list of photos.  So I have these photos in this result.  What do I need to do then?  I need to add them to the collection.  So that's this.add.  And I have to do that through the dispatcher, because the  adding to the collection has to be done on the UI thread.  So I have to dispatch back to my UI thread.  I'm specifically doing it like this.  You don't have to do it like this with all this  task, et cetera, et cetera.  But if you don't do it like this, all the fetching and all  the calculations will also run on your UI thread.  And that's what we want to avoid.  So that's why I'm starting a task here.  I run the dispatcher.  I add all the items to the internal collection.  I increase the current page.  It's just used for internal purposes.  And I return the amount of items I got, because that's  what's expected by my interface.  And with that code, I'm actually done.  This is all I need to do to get incremental load support.  Now, there was something new introduced in Windows Store  Apps 8.1.  There we go again.  And that was incremental data templates.  So at the moment, we already know about UI virtualization  and data virtualization.  Well, here's a third thing that might help in some cases,  some specific cases.  And we're now talking about one recipe data template.  So as you could see, those recipes are loaded at once.  So data in there, the image is loaded, the image text is  loaded, and then it's pushed to composition and shown.  What incremental data templates do is they allow us to  load a specific part of the template first and display  that, and only afterwards display another part.  So that could mean that I could already show all the text of  the recipes, so the name of the recipe, and load the image  afterwards.  That can actually, it will never improve your performance.  It will actually slow down your performance, but it will  improve the perception of performance your user has,  because you already see something on screen, and it  doesn't have to wait for both the text and image to be  loaded, you only have to wait for the text, and then the  image will come afterwards.  So this allows us to incrementally show elements  from a data template instead of all at once.  Now, do you do that?  Well, there's new event.  You handle the container content changing on ListView  Base, and ListView Base is the base class for  GridView and ListView.  And from there, you just go and look at what you want to  show first, and then pass that in, and then register a  method for the second pass, register a method for the third  pass, and so on and so on.  There's quite a lot of code.  I'm going to show you how it's done.  Let me first show you what the effect is.  If the internet is, if this is slow enough, it will work.  It's not slow enough.  I'm going to scroll, and if you look carefully, oh, screen  gone.  Duplicate.  Ah, yeah, that's better.  OK, so this is using incremental, the incremental  collection from before, laid out a little bit differently, and  data templates that are incremental as well.  So if I go fast enough, you see it already.  So first, the text is shown if text is available, and only  afterwards, the image is loaded.  So this does give you, user, the perception that it's going  faster, which can definitely help.  So we already see sparse of data.  Now, how do you do that?  This has to be done in code behind, by the way.  I'm not a very big fan of it, but it does work.  Sometimes for performance, you kind of have to throw out  best practices as far as design patterns are concerned.  So it's a bit of a trade-off.  Let me show you that.  That's not it.  It's the third one, I think.  This one.  I, of course, have to find it.  Oh, here we go.  So first, the XAML code.  It's actually very little to do with XAML.  One thing you see here, my grid view with recipes, it has  the container content changing event handled in code behind.  What happens then?  That's what I do.  So I get, in this content container changing, it will be  triggered.  This is the first pass, so it should be no.  What I have to do then is I have to look at the arguments  which contain the item container, and that item container  in turn contains the template route.  So I actually have to go and traverse that to get to, in this  case, first-time, first-time, first-time, first-time, first-time,  in this case, first-time, the text block that will show my  recipe title.  So that's the first thing I have to do, which is this code.  So I try to find all the elements in my data template.  The ones I want to show, I set to visible, the ones I don't  want to show yet, opacity zero.  And then I need to fill in the text of that title element, so  that title text block.  I always get the item passed in and the template itself.  So I can do everything I need with this.  So from the arguments item, I get the underlying data.  From the arguments item container, I get the data template.  So what I do then is I set the title's text to the title  from the data.  And then I need to register an update callback, which is the  method that will be triggered after this method is done.  So the second time, the second pass is used for loading the  image.  And then I'm in the show recipe image method, which again gets  these content content, container content changing event  arguments.  I find the picture in this case, that's the name I gave to the  image.  I set it to visible and I set the source.  That's how you do this.  Now you can immediately see this actually breaks data binding.  It's an anti data binding pattern.  So should we use it?  Yes and no.  It depends on what you think is more important.  But for some cases, it does make sense.  I mean, for the end user, it probably makes sense.  If you're an architect or a project leads, it probably doesn't  make as much sense.  So it kind of depends.  Okay, so the last thing I want to show you is this one.  I'm not going to show the slide again because I have to be in  code anyway.  That's the most important thing to one common mistake that's  made often.  Using async wait will not offload to a background thread.  Never, ever.  That's a very important mistake that's often made.  We often think that, okay, well, I'm going to use async on my  methods and in that method, I'm going to use await.  So this will run on a background thread.  Well, that's not true.  If you don't do anything specifically, it will run on your  UI thread.  So the only thing the async keyword does is state, okay, this  method can contain an await statement.  And the only thing the await statement does is, okay, run this  code and return once it's completed.  But if in the code that you're awaiting, you're not offloading  anything to the background, then that will still run on the same  thread you call it from, which is the UI thread.  Then the next question is, why does this work for all those  built-in API methods?  Because if you await a file system not open, well, it will run  in the background.  Well, that is because internally, Microsoft always starts up  tasks.  They start up new tasks, and if you start new tasks, that will  run in the background.  So I'm going to show you this because this is how, this is  probably next to UI and data virtualization, the most important  thing you can do to offload stuff from your UI thread.  And I'm just going to show you first how to not do it and what  the effect is.  I have a method here.  Async returns a task, but in that method, there's actually  nothing offloaded to the background at all.  So I could, if I use a task that run in here, this will be in  the background, but this time, not doing it.  I'm just writing out stuff to my output window.  And I do that once I click an item in my grid view.  So let's see the effect of this.  You'll probably know what's coming.  It's going to go bad.  Okay, that's the second screen, I think.  Okay, so I can nicely scroll, and I click, and you'll have to  believe me now.  I'm scrolling, but this doesn't work anymore.  My UI hangs, and why is my UI hanging?  Because this code that's putting all this in my console  window is now running on my UI threads, even though I'm using  Async, await, et cetera, et cetera, et cetera.  So how do you solve this then?  It's simple.  You have to, for your own code, your user code, you have to  manually start task to ensure it's scheduled on the background  and no longer on your UI thread.  So it's actually pretty easy.  You can either do that in this method, or you can do that here.  And let me start that up again.  And if I now go and do the same thing, once it's loaded,  there we go.  To it was, I think, runs.  I click, and I can still nicely scroll, even though it's  outputting those same numbers.  So that's how you offload stuff from your UI thread.  And it actually also proves that unless you do something about  it, button click actually does run on your UI.  OK.  So that was actually, except for the hidden slides, which I  didn't want to show anyway.  That's actually the last thing I wanted to show you.  Right on time, I guess.  Now, is there more to be said about performance?  Yes, of course there is.  You might wonder why I'm not using a performance profile,  but only a memory profile.  Well, performance profiling is something you typically do to  profile how long a specific method takes, something like that,  while when you're working with XAML apps, your problems typically  don't stem from that.  They stem from bad UI virtualization, bad data virtualization.  There's a lot of stuff to be said on working with animations,  dependent or independent.  There's a lot of best practices on working with media,  the file system, application lifecycle is not one of those.  It's too much to put in one hour.  So I kind of picked out the ones that most mistakes are made against.  If you want to know more about this, I'm going to put all these  on my blog within a few hours.  And there's actually a plural site course I made on Windows  for app performance as well.  And I think if the guys are still there, they'll give you a free  voucher for the plural site course.  So that's about all I had to say.  If there are any questions, feel free to ask them.  No?  Okay, so I thank you to stay till the end of the conference,  in the end of my session, and I hope it was useful.  Thanks.  Thank you.
Kevin_Dockx_-_Windows_8_0_20255.png Kevin_Dockx_-_Windows_8_20256_20303.png Kevin_Dockx_-_Windows_8_22632_23015.png Kevin_Dockx_-_Windows_8_24192_24383.png Kevin_Dockx_-_Windows_8_24384_25175.png Kevin_Dockx_-_Windows_8_25176_25391.png Kevin_Dockx_-_Windows_8_25392_25739.png Kevin_Dockx_-_Windows_8_25740_25787.png Kevin_Dockx_-_Windows_8_25788_25847.png Kevin_Dockx_-_Windows_8_25848_26027.png Kevin_Dockx_-_Windows_8_26028_39839.png Kevin_Dockx_-_Windows_8_39840_40031.png Kevin_Dockx_-_Windows_8_40032_40223.png Kevin_Dockx_-_Windows_8_40224_40271.png Kevin_Dockx_-_Windows_8_42840_43163.png Kevin_Dockx_-_Windows_8_43164_43883.png Kevin_Dockx_-_Windows_8_43884_47591.png Kevin_Dockx_-_Windows_8_47592_48371.png Kevin_Dockx_-_Windows_8_48540_48791.png Kevin_Dockx_-_Windows_8_48792_50495.png Kevin_Dockx_-_Windows_8_50496_50687.png Kevin_Dockx_-_Windows_8_50688_50735.png Kevin_Dockx_-_Windows_8_50736_50783.png Kevin_Dockx_-_Windows_8_50784_53471.png Kevin_Dockx_-_Windows_8_53472_53711.png Kevin_Dockx_-_Windows_8_53712_53759.png Kevin_Dockx_-_Windows_8_55008_55379.png Kevin_Dockx_-_Windows_8_55380_56039.png Kevin_Dockx_-_Windows_8_56040_57455.png Kevin_Dockx_-_Windows_8_57456_57503.png Kevin_Dockx_-_Windows_8_57504_57551.png Kevin_Dockx_-_Windows_8_57552_60923.png Kevin_Dockx_-_Windows_8_60924_61067.png Kevin_Dockx_-_Windows_8_61068_61115.png Kevin_Dockx_-_Windows_8_61488_61811.png Kevin_Dockx_-_Windows_8_61812_61871.png Kevin_Dockx_-_Windows_8_61872_61955.png Kevin_Dockx_-_Windows_8_61956_67751.png Kevin_Dockx_-_Windows_8_67752_67799.png Kevin_Dockx_-_Windows_8_67800_67847.png Kevin_Dockx_-_Windows_8_67848_68099.png Kevin_Dockx_-_Windows_8_68100_68867.png Kevin_Dockx_-_Windows_8_68868_68915.png Kevin_Dockx_-_Windows_8_68916_69047.png Kevin_Dockx_-_Windows_8_69048_69479.png Kevin_Dockx_-_Windows_8_69480_69551.png Kevin_Dockx_-_Windows_8_69552_69623.png Kevin_Dockx_-_Windows_8_69624_69683.png Kevin_Dockx_-_Windows_8_69684_69755.png Kevin_Dockx_-_Windows_8_69756_69899.png Kevin_Dockx_-_Windows_8_69900_69983.png Kevin_Dockx_-_Windows_8_69984_70031.png Kevin_Dockx_-_Windows_8_70032_75695.png Kevin_Dockx_-_Windows_8_75696_75755.png Kevin_Dockx_-_Windows_8_75756_75803.png Kevin_Dockx_-_Windows_8_75804_75851.png Kevin_Dockx_-_Windows_8_75852_78575.png Kevin_Dockx_-_Windows_8_78576_79175.png Kevin_Dockx_-_Windows_8_79176_79223.png Kevin_Dockx_-_Windows_8_79224_79535.png Kevin_Dockx_-_Windows_8_79536_79631.png Kevin_Dockx_-_Windows_8_79632_85307.png Kevin_Dockx_-_Windows_8_88968_89267.png Kevin_Dockx_-_Windows_8_89268_89543.png Kevin_Dockx_-_Windows_8_90600_90899.png Kevin_Dockx_-_Windows_8_90900_90947.png Kevin_Dockx_-_Windows_8_90948_91079.png Kevin_Dockx_-_Windows_8_91080_91595.png Kevin_Dockx_-_Windows_8_91596_91643.png Kevin_Dockx_-_Windows_8_91644_91691.png Kevin_Dockx_-_Windows_8_93816_93875.png Kevin_Dockx_-_Windows_8_93876_94011.png