>> Ben Lower: Okay. So my name is Ben Lower, and I am the sponsor for ZapFest. And if this is your first time joining us, welcome, and if it's not your first time, welcome back. And ZapFest is a series of events where we're trying to connect developers or people interested in developing apps for Windows Phone, connect them with internal experts who work on the product here at Microsoft. And before I introduce our speakers tonight, I wanted to mention that tomorrow I'm actually going to do a blog post about a contest that we're working with Core77 on. And Core77 focuses on design. So they have a huge audience of designers, and they've been running the contest since last month to get great design ideas from designers in the area of productivity apps for Windows Phone. And we're expecting that a lot of these designers are going to have a need for development help. So I hear from developers all the time, hey, I don't know what my next idea is. If your coding is like mine, I can build an interface that only a developer could love. So I always love to work with a great designer. And so I've posted the link here at the top, which is just the overall contest that's going right now if you're interested, but the link at the bottom for developers is -basically it's a self-referral page, and so if you're interested to put your hat in the ring and say, hey, I'm interested to look into helping some of these designers bring their apps to market, please do that, because we've gotten some designs in already. I think we've had about 67 submissions, and some of these things are really amazing. You get great designers and their ideas. Things look really good. But we need developers to help. So please, if you're interested, check that out. You can email me if you have more questions. I also want to make one more plug for something that we started doing recently with loaner devices. So we have devices here tonight if you want to see the new Samsung Focus S, the HTC Radar or the Samsung Focus Flash. We've got those if you want to check them out. But we also make devices available on a loaner basis if you need to test your app with some new hardware that you don't normally have access to. So if you want a loaner device, email ZapFest-Devices and we'll get you squared away. So without further ado, it's my pleasure to introduce Stefan Wick, who is a principal test lead working on Windows Phone, and I'm really looking forward to his presentation. So, Stefan? >> Stefan Wick: Thank you very much, Ben. I appreciate the invitation. Hello, everybody. My name is Stefan Wick. I'm a test manager on the developer platform team in the Windows Phone group, and I'm responsible for the Silverlight platform in Windows Phone. I want to talk a little bit about testing and optimizing your Windows Phone manual applications today and hopefully I can give you and handful of useful tips that you can use to improve and optimize your apps that you have today or that you might write in the future. A little bit of motivation up front here. I'll give you a second to read the slide. So I don't think actually, you know, buying a lottery ticket increases your odds of success, but instead I think really understanding the platform and optimizing your app to take best possible advantage of all the capabilities and testing your app to find your bugs and to make your app more robust and more performant is actually the key to success here. I'm not going to talk about money, but if you want your app to be in the top 100 or whatever of the marketplace, I think the key differentiator between your RSS reading and the next person's RSS reader is probably how performant is it, how well it is designed, how responsive is it to your input and so on and so forth. And those are all things that you can control, and with a few little things you can easily do -- you can make your app look better than the next person's and maybe that gets you from a three-star rating to a four-star or five-star rating. And those are the apps that will bubble to the top. So I also have a little bit of a hidden agenda here today. So I guess it's not that hidden now that I talked about it. But I want also to motivate you guys to actually upgrade your apps to 7.1. So how many of you already have written some 7.0 apps and published them in the marketplace? Quite a few. How many of you have upgraded them to 7.1 yet? Not too many. So I think it's a good goal for me to maybe motivate the rest of you as well to do that step. And along those lines there was actually an interesting thread just today on the Windows Phone developer discussion AS, if some of you follow that. There were a few people who have added some instrumentation to their app to find out how many of their users are already running Mango versus 7.0, and they actually found that the vast majority already runs on Mango. So that is another good data point that hopefully motivates people to actually put your effort into building 7.1 apps, because that's where the majority of the customers are and that's also where you get the best performance and best appearance for your apps. So let's take a quick look at the buckets of manage improvements, and I'm not actually going to talk about all the features that we added in Mango, just taking a look here real quick at the improvements in the existing features from 7.0. We can put the improvements in three big buckets. There was one, the general improvements that are baked in the platform. Every app will take advantage of those. If you have a 7.0 app, you run it on Mango, you will get better scrolling, you will get a lower memory for print and you will get better video playback, just to name a few. But then there is a second bucket where we improve the default behavior for 7.1 apps, but we didn't change it for 7.0 apps. That is because of our high compatibility bar that we have for 7.0 apps, and some of the changes we introduced would have broken existing apps, so we couldn't just make a default for everyone. Examples for that are fast-app switching and also our new XAML parser. Everyone know what fast-and switching is? Do we need a demo or ->> Ben Lower: I think an example would be good. >> Stefan Wick: Okay. Just to -- let me just launch a few apps here real quick and then I navigate out of them forward. So now I have launched a few apps, and when I go into my app-switching mode by holding down the back button, I get into this screen where I can see all my apps that are running on the back stack and I can really quickly switch between those different apps. So this is a very seamless experience for the user. You don't have to weight for the app to relaunch or deserialize the data. Everything is right there where you left it off and you can continue. So this is something that your app gets for free just by recompiling it as 7.1. If your app is still a 7.0 app, you don't get that feature even when you run on Mango. So then there's the third bucket which I call here like new optional behaviors in 7.1. Those are behaviors that, you know, your app may or may not want, and so you have the option to use an API or property to opt into the new behavior and then take advantage of it. And this is what I want to focus on for the most part of the talk to give a couple of those examples of where you can do a little bit of work in your app and get some really good improvements on 7.1. So first thing I want to talk about is a very simple feature, actually, and very easy to enable in your application. The background here is in 7.0 we only supported 16-bit per pixel rendering in third-party applications. Even though most devices actually were able to display 32 bits per pixel, you couldn't take advantage of it. And Mango we now enable that, but we didn't make it the default, again, to maintain compatibility and consistency with existing experience. But in your app you can easily opt into it. And let me just pick a random Visual Studio project here. The way to do this is very easy. You just go to your WM app manifest dot xml in your project and it's just one property that you set here. And it's conveniently named bits per pixel, and so by default you don't have this in your manifest. So the default is empty, which is 16, but if you set this property, you opt your entire app into this new rendering mode. And that gives you some pretty significant advantages or improved rendering, specifically for scenarios where you render photos or you have designs that take advantage of gradients. So if any one of you ever tried gradients in your 7.0 application, you probably noticed some pretty ugly banding and then you probably stopped using that. >> Ben Lower: Is it okay to raise questions as we go? >> Stefan Wick: Yes. Please. >> Ben Lower: So a question from the folks online. What's the performance hit, if any, for opting in? >> Stefan Wick: Yeah, the performance is really low on this one. So I would still recommend if you opt in that you retest your application in both scenarios and make sure there's no noticeable difference. But there should be only very minimal difference in terms memory usage and no difference in interactivity. Yes, please? >>: [inaudible] >> Stefan Wick: Really good question. >> Ben Lower: Can you repeat that question? >> Stefan Wick: The question was does it apply to X and A applications as well. The answer is yes. So -- oh, one important thing to point out here is for video applications, we actually automatically opt you in on Mango. So this was a decision we made because we thought most video applications are kind of full-screen anyway, and there is no other UI that would be affected, and are the video playback in 32 bits per pixel looks so much better and so much more natural that we thought that it's the right call for video in general. Yes, please? >>: So the splash screen, sometimes you run -- like if there are gradients, there are shifts. Will this help with that as well? >> Stefan Wick: No, the splash screen not affected by this setting. >>: Because in my experience when I designed and planned and put it in Windows Phone, sometimes there is a banding effect. >> Stefan Wick: Yeah. So the question was about the splash screen. Splash screen is not affected by this. So you want to make sure you design your splash screen that it still looks okay in the 16-bit mode. Okay. So I do have a quick demo for this as well, but in case the projector doesn't show the difference, I also put it on the slide here. And I hope you can actually see this. The banding on the left and no banding on the right -- can you see these stripes over here? So this is a typical effect that you get in 16 bits per pixel. So on the left is the 7.0 case and on the right is Mango when you opt into the 32 bit per pixel mode. It actually is much more visible if you look at it on the device itself, and, of course, it depends on you're seeing the more gradients you have and, you know, if you have a photo with like a sky, you see it very noticeably. Maybe if we can switch to the projector, we can show it here. So I have the same app in 16 bits per pixel and there bits per pixel. So does it show? Yeah. So you can tell which one is which, I think, and when you animate it actually is even more noticeable. And if you look at the device directly, you can actually see it much more visibly. So it's something you might want to try on your app. If you have lots of colorful things, it might help you get a significant better rendering experience. Yes? >>: Does that apply to the live tile at all or is that all handled differently? >> Stefan Wick: The question is does it apply to the live tile? No, it does not. So live tile is not affected by this setting. >>: Does that mean the live tile is, by default, 32 or is it ->> Stefan Wick: No, I think live tile is, by default, 16. So the next thing that is kind of new in -- let's go back to PowerPoint. The next thing that is new in 7.1 that you can opt in very easily is the background image decoding. So we did a lot of work in 7.1 to improve the list scrolling scenarios, and specifically when you have lots of images in your list, you may have seen problems in terms of responsiveness and stuttering in your list. So one of the things that we have enabled in Mango is to move your image decoding on a background thread, because in 7.0 the image decoding always happened on the UI thread, which then interferes with your input and your interactivity on your list or whatever piece of UI you have. With a simple option by setting creating options to background creation you can move that to a background thread and achieve a much natural experience for the user. Of course, in the end the time it takes to decode an image doesn't change, but by moving it to a background thread, the perceived user experience is much better. Let me try to demonstrate this here on the projector. So I have two identical apps. One has the background creation flags set [inaudible], the other didn't, and so what I want to do first is just kind of scroll as fast as I can down here. So first I can see -- so both devices are running Mango, and so the responsiveness is kind of nice. The scrolling seems okay and natural. But now when I try to scroll as fast as I can, you notice on the left one there's a lot of these completely blank items where the UI just completely disappears for a few seconds even. And I don't have this in the right application because here my image decoding happens on the background thread. So the images, you know, they still take a while and then they pop in, but my text and the rest of my list items is still there as the user will expect. And another thing to demo here this improvement nicely is if I change the images in my list by clicking this button here and then interact, you see the one on the right responded immediately while the one on the left was actually stuck for a good number of seconds before it even started to scroll. So this is a big thing that you can enable in your app with just one property setting. Yes, please? >>: This property is available for creating the programatically, right? >> Stefan Wick: You can do it programatically as well, yeah. If you create a bit map image instance, you can set the create options property at that point. >>: Are you sharing this PowerPoint? >> Stefan Wick: Yeah, I will be sharing the PowerPoint and also the demo applications. Yeah. And this one here I think is actually up on our [inaudible] block already for a while, so you can also get it from there. So that was the second one. Really, really simple thing that can give you big improvements in your app if you're dealing with images a lot. If you just have one image, then you may not care. But especially for lists, it's a really good improvement. So we've seen the demo. The next one -- I actually want to talk about that quite a bit -- is memory testing and debugging and optimizing. If you're new to Windows Phone development and you come kind of from a desktop background, you may not think about 10 megabytes here, 100 megabytes there, you know, who cares, right? But on the phone, memory is one of the resources that are very, very limited and precious. So generally we want apps to stay under 90 megabytes in the certification process. So you do want to be careful how much you allocate in your app. And, most importantly, you want to be careful that you're not leaking any memory, because we've seen apps that pass the certification because -- yeah, they don't exceed 90 megabytes at that point, but when an actual user uses them in the real world for more than 10 minutes and the app has a leak, then you easily go up to 200 or more megabytes, and at that point you're likely to crash on the device. And we're actually see a lot of what's in reports where third-party applications are crashing with out of memory exceptions. So that is a real problem. And a lot of it has to do with people's apps are leaking. There was a question? >>: You mentioned certification. So how is certification done? Is it, like, manually people would run the app and measure ->> Stefan Wick: Yeah. So it's a mix of some automated and static analysis and actual manual testing. So there are humans who are exploring the app, doing exploratory testing as much as they can. Of course, they don't fully understand each app so the mileage may vary. But, yeah, humans are testing that. But then the real world is always different, right? You can consider kind of a Facebook application and you test it with five friends, everybody may be fine, but then someone has 50 friends. Now does that mean your memory usage is 10 times as much? Then you might have a problem. So that's something you also want to consider in your testing. Put it to it the real world test with real world data in a real world environment. Also consider monitoring your heavy objects. And it's something I will demonstrate in a second. Just understanding, you know, the number of instances of your pages or your user controls on the heap is a very useful metric during the development and testing of your app to actually identify any leaks your application. And it is really a fairly common problem that people have leaks in their app. Initially people think, oh, it's managed code so how can I leak, right? There's garbage collection. What can go wrong? But almost all apps that we have analyzed that have performance problems, we've found that they have some amounts of leaks in their managed code. And that is something that you can prevent up front. Also I wanted to call out, even if you have just a tiny little thing in your UI that has a problem and leaks like, you know, a single element that is maybe not well written like a user control and it leaks, this can actually cause or typically does cause your entire visual tree to leak because in the tree braced framework that we have, each element has a reference to all the children as well as to all their parents. So if one guy leaks, it keeps everything else alive, the entire subtree. And so this can be your page. When you navigate back, your entire page may be leaked, and if that has a bunch of images and our heavy of data objects, one navigation is leak 5 megabytes right there. And last but not least, I want to encourage people to take a look at the new 7.1 profiling tools which include a memory profiler, which I will also show in a second, and that is a very useful tool to actually track down your bugs. Once you have a suspicion there is a leak in your app, you can use the profiling tools to actually get to the bottom of it. So for demoing memory testing, I'll switch you over here to my emulator. And so I have a little app here that has a small problem. So this is just a dummy app. It just has two hyperlinks here. On the top I just have some diagnostics so you can see what's going on here. And so all it does is it navigates to one page which shows a photo, and I can navigate to a second page which shows a different photo. These are pretty large photos. I picked large ones so that you can easily see the memory problem. So let's monitor what kind of -- what our usage is. So we're already up to 16 megabytes here, so let me repeat this cycle here a few types. So I'm going to these pages repeatedly as a user, and so now my memory usage is already up to 29 megabytes, so this is pretty disturbing because typically, or the way it's designed, when you navigate back from a page, that page becomes eligible for garbage collection and it should just disappear at some point. So it could just be that garbage collection hasn't kicked in yet. That's a possibility. And actually it looks like that's what happened here. So I can force garbage collection and my memory goes down, but it's still not where it started, where it should be, and my little heap tracking indicator here shows that there seems to be a problem with the second page class because all those three instances are still there while the first page instances have been collected. Let me kind of try to validate this a little more. When I repeat this with first page, it always goes nicely back to zero, and when I do this with second page, it just keeps going. And now I'm at 5 and my memory usage is at 22 megabytes and I'm really on a bad trajectory here and I will soon crash if I keep doing that. So let's first take a quick look how I'm tracking the data here in my testing and then we'll take a look how we can use the memory profiler to get to the bottom of what the bug might be and how we can fix it. So what I'm doing here to display my text in my little diagnostics helper, there are properties that we expose as APIs that you can just query to get the current and the peak memory usage. So that's pretty straightforward. To get the number of instances for my pages, I have exposed a little static on these classes, a public static that just counts the instances. So whenever I hit my constructer, I increment them, and whenever my page gets finalized and collected by garbage collection, I decrement the counter. So this way I can just keep track of what's currently active on the heap. So let's start the performance profiler. Why is this not -- oh, I'm on the -- okay. Interesting. And we want the memory profiling here at the moment. There's also execution profiling, but we'll focus on memory profiling, obviously, for this problem. So this will now launch my application with the profiler attached so we can collect detailed data about the allocations and who's holding onto what. >>: [inaudible] >> Stefan Wick: Oh, yeah. That's -- good catch. It was actually running over here. Okay. I have to wait a second until it's done analyzing this. So let's close this out, and we want to run on emulator. So this should start in a second. Okay. Here we go. So let me just go through this iteration real quick -- oops. I think that was not what I intended. Let me try this again. I don't know why it just crashed. Okay. Let's try again. Okay. So we go to second page. Let's do it -- okay. I don't know why it exits on me. But maybe that's actually enough data to look at this. So I have all my memory data here. It tells me excessive allocations. Okay. That's good. I can probably figure that myself. And I get a heap summary. So there's lots of data here. I will not be able to get into all the details here, so that's probably one talk of its own. But I want to take a look at the retained allocations at the end here because that's kind of what's left over. And so from our own initial testing, we already had the suspicion that something with the second page is not getting collected. So I'm going to sort by type name here and find my second page type somewhere down here. Phone app, second page. So here it is. And I can scroll over here and I see, okay, there are two instances. That's not what I expect. So I can look at these two instances. And so let's take a look at the first one that was created. So that's definitely one that should not exist anymore, and so now I'm missing of the data here. So give me one more try. Actually, let me restart the emulator. Sorry about that. Give me just one second restarting the project and then do the profiling from scratch. So what I want to get to is in the data that the profiler spits out for my instances for second page, it can tell me what are all the objects that hold references to that page, and by looking at that data, I can get a really, really good hint of where is the problem, what is the culprit in my code that is causing my page to not be eligible for garbage collection, because obviously there's something in the app that still has a reference on it, so the garbage collector thinks it cannot collect that instance yet. Okay. So hopefully we're back in business now. Okay. So this looks much better. Now I can stop my profiler and hopefully I have the full data set now. Okay. This looks pretty good. So let's analyze this and look at our heap again. Allocations at end and we're scrolling down to [inaudible] and we're scrolling down to the second page instances. Here we go. Okay. So now I can go ahead, I can either look at the object graph of what it is referencing or the GC roots. Those are the roots that prevent my object from being garbage collected. So if I follow this down here, I get a really good indicator here. So there appears to be a context menu that is holding reference to my page at the end of the day. Actually, it's holding reference to the image, and since the image has a pointer to its parent and the parent at some point is the page, everything in that page including the image and the context menu and everything else is just leaked. So some of you may be familiar with that bug because that's actually a bug that was present in the tool kit. So for those of you using the Silverlight tool kit, the context menu is a control that ships on code packs with the tool kit, and it had this bug. So the fix for me now would be very easy here. I'm just using a very old version of the tool kit, and if I just upgrade to the current August version, the bug will be gone. So that's the fix here. But another possible fix would be -- if you didn't have that fix available, another possible fix here would be on the navigate event before the page goes away you can basically just unhook the context menu from its element and this way it doesn't cause any harm. The context menu may still leak, but everything else will be collected. So that is kind of a work-around you can do. If you consume a third-party control that has a leak on your page, then you can just throw it out of the tree before the tree goes away. This way everything else becomes eligible for garbage collection. Yes, please? >>: So question: Would it be a bad idea to call the garbage collector explicitly in your app? >> Stefan Wick: The question was is it a bad idea to call garbage collection in your app. Not necessarily. So there are different camps on this one. It depends on your app and how do you it. You don't want to call it all the time because that also gives you a sense performance hit, right? But if you kind of know what you're doing, then it's okay. But generally you should not have to do it. So the garbage collector should be smart enough to do the right thing. >>: There some general guidelines around when you might want to consider ->> Stefan Wick: Well, if you have a situation where you know the user isn't interacting with the app right now and there are cycles available, you might as well kick it off because it's not causing any harm at that point and it might lower your memory pressure. So that would be okay. But if the user is interacting with the app and scrolling and sliding and flicking, at that point you don't want to call it because then the user will see stuttering and things will just stop for a moment. Yeah, generally you shouldn't have to do it. And obviously calling GC explicitly doesn't help with situations like this where something holds a reference to your objects because they are just not eligible for garbage collection. Okay. So, actually, let me go back to my little app here real quick. So obviously this is kind of a contrived sample and demo, and you don't want all this kind of UI a top of your application to always monitor, you know, all the different pages that you have in your app or other objects and memory usage and have a GC button and whatnot. So I want to just use this opportunity to kind of highlight another Mango feature that we have added, and that comes in handy here because that enables me actually to move this piece of UI out of my phone and I can just throw it into my -into an application running on my Windows desktop and monitor things that way. Let me just show that real quick. I'm going back to my project here. So I have a little controller app here. This is just a standard WPF application that I put, and I just put the same UI in there pretty much. And so now when I launch my phone application -- now it's not working. It should actually connect to this one. Maybe it's because I'm running also the device here. Okay. Let me try from the device. Okay. It looks like the demo gods are not with me today. It worked before in my office. Anyway, the general idea is that I just put my monitoring UI up here in a Windows application that I'm running on my desktop and I'm using sockets to connect to my phone or to my emulator, and this way I can actually operate the app and monitor anything that's going on there. So ->>: Does the feature have a name? You said it was a new feature. Are you referring to sockets being the new feature? >> Stefan Wick: Yeah, sockets being the new feature, right? So I'm just using that to enable the connection between my desktop app and my phone application here. Okay. I'm not going to debug this here. So maybe I'll get it working after the presentation, but hopefully you kind of got the idea. So that is something that can come in pretty handy for debugging purposes, or, you know, if you just want to do some logging and things like that, this can be a useful feature you can add just during the development process. So next topic, very important, kind of end-to-end testing for your application. I think most of you are engineers, so I don't need to explain the importance of testing and the value of testing. But, still, I want to highlight maybe some of the obvious benefits here and then show a little bit of a demo of how this can look like in an application on a phone. So if you're just developing kind of a 99-cent iFart clone application, you know, your end-to-end test is probably not that complex and you can probably get away with just kind of ad hoc testing it and then you're done. But if you have anything more complex than that, you do want to have some structured way of actually going through your app, hitting all your different code paths, all your different pages and controls and your business launching and verify along the way that your state of your application is correct and the visuals look right and that you don't hit any crashes or memory problems. So in simple cases, probably some sort of manual script will suffice there, but if you have a slightly more professional app or you make more long-term investments in your app, you might want to consider having some sort of automated script for that. So that's something where we don't have really any tooling support today to help you with that, but, still, I think it's something that I would encourage you to consider because using the public API servers that we have and using some standard techniques around mocking and inversion of control, you can actually very easily build these kind of scripts that will exercise your application and verify a lot of things along the way. One important thing for that to work is actually that you design and develop your application with testing in mind from the beginning. If you kind of treat it as an afterthought, then it might already be too late and you will not have an easy time to actually do it. Yes, please? >>: [inaudible] >> Stefan Wick: Yeah. So there aren't -- as I said, there aren't many -- there is no real tooling support available for this, and also guidance is very limited today. The parents and practices guys actually put out some guidance along those lines. I think last month they put something up on CodePlex with some guidance. The only other sort of framework that is available is for unit testing. So this is [inaudible] unit test framework, but that won't really help you much with the end-to-end testing because it's fairly limited in terms what you can actually execute. But kind of to show more conceptually how this can look like and what you can do, I have a little demo here in my emulator. So let me deploy that. So I've picked the fuel tracker application, which is -- some of you might have come across this one on MSDN. It's an application -- or it's a sample on MSDN. It comes with a fairly nice article about building an application from start to finish, and that is basically the application that they're building in that article. And so what I've done is -- so I took that application and modified it a little bit to make it more testable and then I wrote some tests against it. So I have here the fuel tracker application. Let me just demonstrate it real quick, how it works. So you can enter your car name, choose a picture for it. I don't have a car picture here, so whatever. And so now that you've set up your initial automater and now that you've saved your car, you can track your fuel consumption. So there's some things to review. And so whenever you fill up your car, you can go ahead and enter your new automater and enter how many gallons you filled up with and then the price you paid for your gallon. And then you can get your average miles per gallon, you see your history, and so on and so forth. So a very simple application, and nothing exciting, but it's still more than Hello World and it's pretty close to something that you could consider a real application. So now the application is here in this project. So what I've done here in my second project, this produces a second zap which basically is a super set of my fuel tracker zap with my test code added. So this way I keep it nice and separate so my shipping zap doesn't have any of my test code and I have a secondary zap that uses this exact same code that I'm shipping plus my tests. And then these are just kind of [inaudible] libraries. So now when I launch my test application, I get to a test manual or test page first, and from here I can launch different tests against my application. I could just do a manual test which will just launch my application and I can go through it manually. This actually is pretty useful -- can be useful because I also have some additional sort of features here that I can enable for my testing. I can enable frame rate counter, memory counter, and some other debug flags that help me identify problems or issues in my application. I can also turn leak detection on, which is something similar to what I've shown in the previous demo where I just kind of count the instances of my interesting objects, and whenever I see something didn't go away after page navigation, I basically fail my test. So with these flags the manual test can actually be fairly interesting as well. So I also have unit tests here, and this is using the [inaudible] unit test framework that you may already be familiar with. So this is just standard .NET stuff for unit testing. This is nothing different from what you probably are already familiar with. But then the end-to-end test, that's probably the more interesting piece here. So in the end-to-end test, that's basically where I have my automated script that go through the entire procedure of my -- of using my application and actually kind of hits every page and every control and does something useful with it. Let me actually show the test finding a bug. So if I run my end-to-end test now with leak detection on -- let me run it again -- so now at the end of my test it actually flags it that, hey, there's a leak, and so I can see, oh, my fill up page didn't get collected at the end so there's probably a bug. So my test failed. Let me go fix this bug real quick. So I go to my views here, fill up page, and of course I already know the bug so it's easy to fix. Otherwise, I would use the profiler to tell me where the bug is. But the bug here is kind of a standard .NET bug that people easily do. I subscribe to a static event here for touch input, but I forgot to unsubscribe in the end. So that one keeps my page alive. So the fix -- luckily someone already coded it up here -- the fix is before I navigate away from my page, I go and unsubscribed from my event so this way I don't leak my page. So let me rebuild the app and deploy. And so now I can run it again. Let's not forget to turn on the leak detection, run my end-to-end test. And now the test passed. So the system works -Yes, please? >>: [inaudible] >> Stefan Wick: Yeah, sure. I'll definitely share it. And I can also -- I don't know how much time -- we have eight minutes left, so I can also go a little bit into the code right here. And so then my last option that I have here is just a stress test. It's very simple. What I'm doing here is just I run my end-to-end test just in a loop. That's basically all I have. But you can certainly get more creative here and more crazy and do more stressful things. So maybe we can pick a small piece of the code here and look at that. So one thing that's kind of traditionally challenging if you're trying to test your phone application is some of the launches and choosers that you interact with. For example, in this application I have the photo chooser, so I can pick my -- the photo for my car from the library. So what happens when you run your app, you launch the photo chooser and that actually puts your app in the background and the chooser is in the foreground and then you're no longer in control, right? And so that's kind of challenging for tests. What I've done here is I've built a little extension for tasks, and so in this case I only implemented it for the photo chooser task, but the same would apply to others as well. So the way the photo chooser task works in the platform is it just has a show method which launches it and then it has a completed event that fires when it's done, and when you get control back then it gives you the pointer to the picture that the user has picked. So what I'm doing here, I'm adding basically an overload to the show method that also takes a delegate to completed method. And so now I just have two different execution modes. In case the user uses the application, I just do the a lot of same thing I would normally do. I'd just call show on my task and then when the completed event fires, I erase the other completed event that my application is subscribed to and everything just works exactly like it does in the normal world. But if I'm not in the user execution mode, meaning I'm in the test automation mode, then I go down here, and what I'm doing here is I just skip launching the task and instead create the result myself and then launch the completed event with that result. So this way I have kind of mocked the photo chooser task and my automation can just continue. Because the goal for me is not to test that the chooser works, the goal for me is to test that the application works, and I just assume the chooser works correctly because that's actually my job and my day job. So that is one example and similar things you can do with, you know, the other parts of the platform as well using mocking or inversion of control type of techniques. Okay. I think actually that's -- yeah, that's all I have. So, yeah, thank you very much. [applause] >> Stefan Wick: And, yeah, I think we still have a bunch of time for questions. >>: Is there any way to see what it happening on the [inaudible]? I have some problems in my app where just something seems to be [inaudible] and I don't know what, and I'm not sure how to find out what exactly is happening [inaudible]. >> Stefan Wick: Okay. The question was is there any way to find out what's happening on the UI thread. And so the 7.1 profiling tools actually give you some good indication of what's going on on the different threads. So if you run your app in the sort of execution profiler, you get a breakdown of what's happening on what thread. So I would recommend trying that, see if you can see anything obvious. There's a lot of data that you get, so it might take a while to kind of actually wrap your mind around that and trace it back to, like, what you're doing in your code that triggers it, but it should show you what's happening on the UI thread. >> Ben Lower: So some of the folks online are asking if you would do some more general coverage of the profiler. Since we have some time, they were wondering if you can just show more, because they're really intrigued by what they saw so far. >> Stefan Wick: Okay. For the memory profiler or the execution profiler? >> Ben Lower: They're replying right now. Memory. >> Stefan Wick: Okay. Actually, yeah, why don't we try to debug the other problem here that I just fixed in the fuel tracker application using the memory profiler. So let me put the bug back in here and let's see what the profiler has to say about this one. Okay. So now I have to get all the way to the fill-up page to see the bug. And so the fill-up -- why is it invalid? >>: [inaudible] >> Stefan Wick: All right. There you go. Wow [laughter]. So now -- yeah, now that I got back from the fill-up page, I should have leaked it. So let me stop the profiler and see if the profiler can confirm that and then also hopefully it will point me to the problem. So there's a lot of data now since it took a while to get there. Let's still look at everything here. So my heap summary, allocations at [inaudible]. Oh, yeah. There's actually probably something useful to call out here. I should have actually said that before. So in this view, intuitively, when you look at the types here, you would probably intuitively go by -- sort by size and just look for what are the biggest things that are not collected yet. But in most cases actually that gives you kind of a false -puts you in the false direction because if you look at the sizes here, they're not actually that large. This is in bytes, so we're just -- these are just like 160K or something like that, so that's not really that important. It is important, but not that significant. It's important to understand that many objects in the framework have both a managed memory footprint as well as a native memory footprint. Like when you have an image controller with a large image, the manage image control, that's just a couple of bytes. That is nothing really significant. But the decoded image which we keep in native memory on our side of the framework, that's where all the megabytes are. So in that case -- with that in mind, the actual managed bytes that you see in the profiler don't necessarily tell you where the big chunks are that are being leaked. So it is more important to look for the instances of objects that should not be there, like the several-page instances that we saw in the other example. But here let's look for our fill-up page -- actually, I need to take a look at the name space here so I can actually find it. It's fuel tracker reviews. Fuel tracker reviews, fill-up. I think that's probably it. No, fill-up page. This one. So this is the one that should not be there anymore because I've already navigated back from it, so that is all leak. So let's see what the GC root says here. So there's a lot of data. It's a slightly more complex page. So this part obviously was not rehearsed at all, so ->> Ben Lower: There's a question as you're clicking through. They're running the profiler on their machine and they don't see the bottom window so they're wondering if you did something special to get the bottom half of the analysis page to have ->> Stefan Wick: No. That should just show up. Maybe they need to rearrange their windows a little bit. That should be up by default. So I didn't do anything here. >>: I thought you had to select like a section of the ->> Stefan Wick: Oh, that's right, yeah. You first want to select a section of ->>: You need to select something on the timeline? >> Stefan Wick: Yeah. Exactly. >>: Okay. >> Stefan Wick: Yeah. So there's -- since I'm looking at the root of the page and the page contains a bunch of stuff, that's why we're seeing tons of roots here. So that is a little bit hard to [inaudible] here right now and pinpoint the exact issue right there. So that takes a little more, I think, time and also practice to kind of know how to get through the data here and actually pinpoint the thing in code. But the good thing -- oh, here we are [laughter]. Sorry. At the bottom. So, anyway, it is something that, yeah, you do want to practice a little bit. I think it's not the most, you know, intuitive thing. At the end of the day, the data is there and can help you pinpoint your leaks, but, yeah, I would recommend practicing that a little bit maybe with some sort of contrived leaks that you sort of introduce yourself and then make sure you can see them and then with that knowledge you can expand later to find other leaks as well. >>: So I missed -- as you were scrolling through the list, I missed two thing. What were you looking for when you went through the list, and then when you got to the bottom, how did you know that was the thing you were looking for? >> Stefan Wick: Yeah. So actually there's more data than this -- actually, on my laptop, in this resolution, it's hard to kind of see everything together. There's also the root kind that you may want to take into account, and so we're looking at the end of these -- of these various roots that go all the way down. And, again, it's kind of hard to see everything together here. It also is a little bit kind of knowing some of the normal patterns that you see on, like, every page that is just alive by default versus things that shouldn't be there if they are collected. So I think that goes back to what I said, that you might want to practice that a little bit. And looking at a page is probably kind of the more complex scenario here because there is a lot of things that have references to the page. So you might actually want to pick a simpler example where you just have one control on your page or one panel on your page that contains a leaking control and then inspect what's going on on that panel. And so look at the panel, you know, without that control and with that control and see what the differences are. Okay. Other questions? Yes, please? >>: Would you say that the majority of leaks happen because of unsubscribed events? Is that something ->> Stefan Wick: That is definitely a big class of problems, yeah. So that could easily be the largest class, yeah. >>: Is there a way to kind of separate the event handlers in that place or ->> Stefan Wick: No, issues that not. Yeah, so that's definitely one, but also just another common pattern is where you have maybe some static collections, and so a control that adds itself to a static collection and then later, when the UI goes away, the control is still referenced by that static collection. That's another pattern that's quite -- that you see quite often. And I think in practice, in many cases you will actually find it's not necessarily your leak that you're hitting in your application. If you're using a lot of, like, third-party MVVM frameworks or, you know, control libraries, you actually inherit all of their bugs as well. And so that's another thing you will likely encounter. Especially in the MVVM world we've seen a lot of these problems as well. >> Ben Lower: Another question from online. Do you have any tips around using a dispatcher versus a background worker? >> Stefan Wick: Well, both are fundamentally different, right? The background worker spins up a new thread so you're executing on a whole different thread versus the dispatcher just basically puts the work into a queue on the UI thread and then executes it when the queue is ready to process that. So that's the main difference. So if you want stuff to be off the UI thread, then, yeah, background worker or any other thread is the right choice. If you want or need your work to be executed on the UI thread but you don't want to run it right this moment but only later when the UI is ready, then this picture would be the right choice. Okay. Any more questions online? >> Ben Lower: That's it. >> Stefan Wick: Okay. Cool. All right. Thanks again. [applause]