Performance is an important aspect of all applications, especially apps that run on resource constrained, network reliant mobile devices. As a user, it is relatively easy to tell when a running application is “slow”; what is not so easy is identifying the cause of the performance problems. Making changes to the source code without understanding the effect on performance can lead to unnecessary refactoring and potentially make the problems worse.
What to do? With the release of Windows Phone “Mango”, we can now easily identify the source of our application’s performance problems – all the way down to the functions that are causing the issues. Enter the Windows Phone Profiler tool. You can use the new Windows Phone Profiler to help identify issues with performance in your application including memory consumption, visual tree complexity, application launch time, and identifying long-running functions.
To run a performance analysis session, open your Windows Phone Project in Visual Studio and select “Start Windows Phone Performance Analysis” from the Debug menu, or press the ALT-F1 shortcut key:
Be sure that you are launching the Windows Phone profiler, and not the .NET profiler, which is also found on the Debug menu, listed as “Start performance analysis (ALT-F2)”.
The first thing you’ll see is a page asking you to select the type of analysis you want to do. Unless you know specifically that there is a memory consumption problem, you should always start with the Execution analysis:
Clicking the “Launch Application” link will start up your application on either the emulator or the device with all the monitoring code automatically added to your session. Once the application is started, navigate around your application exercising those features of your application that are the most performance-critical or that are going to be most frequently used by your users. As you put your application through its paces, tracing information will be be automatically collected and recorded by Visual Studio for later review.
Once your testing session is complete, switch back over to Visual Studio and click the “Stop Profiling” link:
At this point, Visual Studio will save all the performance profile data into a .SAP file and add that file to your project. This file will be keyed to your project, as well as the execution date and time of the test (e.g. DatabaseForMango_2011_11_14_17_59_27.sap”. This recording can be reviewed now, or saved for later viewing. The main view of the results is the set of graphs that are provided. These graphs represent a number of different measurements that are all stacked on top of each other to provide a timeline-based view of your applications performance.
Starting at the top, these graphs show
- Frame Rate: This shows the recorded frame rate for each frame rendered in the UI. Low numbers here are potential trouble spots that warrant more investigation.
- CPU Usage %: Shows CPU usage across different parts of the application
- Green bars represent the UI thread – this is the one to watch as high usage of the UI thread causes the UI to become unresponsive to user input. Any value over 50% is a potential problem area.
- Blue bars represent the Application threads – this includes and user-created background threads and the composition thread (higher is better, compared to UI thread)
- Grey bars represent System threads – these are the threads that are NOT part of your application, but represent things like background tasks, etc.
- White bars represent Idle threads – like the “System Idle Process” shown in Windows Task Manager, this represents the available CPU percentage. A higher number means a more responsive UI.
- Memory Usage in MB: Watch this if you get more than 90MB anywhere and run the other test – 90MB is the limit for passing marketplace certification.
- Storyboards: an S is displayed at each frame where a Storyboard is launched.
- Red represents a CPU-bound storyboard (these are bad as they run on the CPU thread and directly impact UI performance)
- Purple represents a GPU-bound storyboard (these are good as they’re run on the Compositor thread and do not affect UI performance).
- Image Loads: An “I” will show up on the frame to indicate where an Image is being loaded into memory.
- Garbage Collection Events: A “G” will show up to indicate a point at which the Garbage Collector is run.
To see the details of the data that is feeding the graph you simply use the mouse to select a region of the graph containing those frames that you want to drill down into. The lower section, referred to as the Detailed Performance Analysis section, will populate with Warning and Informational messages that highlight areas of concern for the selected frames:
From this picture, you can see that two specific warnings are called out related to frame rate problems. For example – the first warning in the picture above contains the following information:
Warning: Very low frame rate potentially caused by a high layout cost.
Total layout time (0.35 seconds) is high. Element System.Windows.Controls.ScrollViewer : ScrollViewer took the most time in layout and is contributing to the low frame rate. This could be because CPU-bound animations are causing layout updates. Go to the Performance Warnings menu in the navigation toolbar and select the Frames view. Sort the frames by clicking the CPU Time column header and select the frames with the highest CPU time. From the Frames view, select the Visual Tree option and identify visual System.Windows.Controls.ScrollViewer : ScrollViewer in the tree.
This warning calls out the low frame rate based on how the layout is constructed relative to the ScrollViewer. The suggested action indicates that we should drill into the Performance Warnings menu and select the Frames view. If you look closely at the Detailed Performance section, you’ll see that right next to the Performance Warnings item is a button that controls a pop-up menu containing several choices beneath it into which we can “drill down” for more information. If you choose the “Frames” option, you will see something like this:
This list of the actual frames selected shows that many of them have a CPU usage well over 50% – in this case there is even one with over 80%! Selecting that frame, and going back to the navigation menu next to the Frames item from before, shows that there are still more levels of detail we can get to for that particular frame. Select each one of the items to get further information about what’s going on with that particular frame. Looking at items such as the Functions option will allow you to see what methods are being called in your application, and will provide links back to your source code for those methods from the application that are being executed. You can also look at the Visual Tree, Element Types and Cache Updates. These error messages, combined with the direct guidance given on where to look for problems and the tool’s ability for you to drill down into the root cases gives you a great viewport into your application to discover potential trouble spots and fix them before submitting to the marketplace for certification.
Now that we’ve seen how the tool works, here are a couple of tips for using it that will help speed you on your way to a speedier application:
- Start with the Execution Performance tests to see if there are any memory issues, as indicated by the Memory Usage graph. If you discover spots where your application is consuming over 90MB of memory, run a second test focusing specifically on the Memory settings. You’ll normally find that any performance issues can be diagnosed with this first test, so only use the second test when memory concerns warrant it.
- Don’t forget to test Fast Application Switching, Tombstoning and the corresponding Activation processes – these are all important parts of your application. To force tombstoning in your application when you press the start button, go into the project properties under the Debug tab and check “Tombstone upon deactivation while debugging”. Otherwise, your app will default to FAS.
- Always performance test on a device – the performance of your laptop will not compare to the performance of your device. This goes back to the old “we’re not shipping this app on your laptop” axiom of testing. The Windows Phone device is much more resource constrained than the typical development workstation, so memory and performance issues will be more likely on the device than on the emulator. Running these tests against the device works the same way as traditional debugging on the device – just change the Deployment Target from “Windows Phone Emulator” to “Windows Phone Device” up in the Standard Visual Studio Toolbar.
Here are some links to additional resources on Windows Phone Performance Analysis:
- Windows Phone Performance Analysis
- How to: Capture and Analyze Performance Data Using Windows Phone Performance Analysis
- How to: Identify and Fix Common Performance Issues Using Windows Phone Performance Analysis
Tomorrow, Gary Johnson will be writing about Background Agents, and how we can use this new feature of Windows Phone 7.5 to execute code even when our application isn’t running. See you then!