New UI Performance Analysis Tool for WPF Applications
In Visual Studio 2013, we added a new XAML UI Responsiveness tool in the performance and diagnostics hub to enable you to analyze application interaction-related performance issues in your XAML Windows Store applications. Since then, we’ve gotten a number of requests to support WPF applications. We’re excited to announce that we have built a new Application Timeline tool which is a replacement for the existing XAML UI Responsiveness tool that supports WPF applications in Visual Studio 2015 CTP 5. Current support is limited to WPF (.NET 4.0 and above) and Windows Store 8.1 applications running on Windows 8.1 or later. We are exploring adding support for Windows 7 in a future release of Visual Studio.
Why use the new profiling tool?
Performance is a critical aspect of any enterprise WPF application. Customers expect applications to load fast, as well as interactions with them to be jitter free and fluid. The Application Timeline tool helps you improve the performance of your WPF applications by providing a semantically-rich, scenario centric view of your applications’ resource consumption. You can analyze the time spent by your application preparing UI frames, servicing network and disk requests, and much more in scenarios like Application Startup and Page Load. This post briefly highlights the features of this tool.
Profiling an application
To profile a WPF application in Visual Studio 2015 CTP 5, open the Performance and Diagnostics hub from the Debug -> Start Diagnostic Tools Without Debugging (ALT+F2) menu. Select the Application Timeline tool and click Start (You can also run the CPU Usage tool alongside the Application Timeline tool). This launches the application in the profiler. Once you exercise the scenario that you’d like to investigate, you can stop the profiling session by clicking on the Stop Collection link, which starts the analysis of the collected performance data.
Now you can investigate the performance report for optimization opportunities.
Inspecting profiling session details
The report shows a chronologically ordered list of interesting events in your application, which directly corresponds to CPU consumption during your application’s execution.
Along with the reports, you are also equipped with graphs that detail the UI thread utilization and the Visual throughput (UI and Composition) of your application. These graphs enable you to quickly spot periods of excessive UI thread utilization or low frame rate which might correspond to poor application responsiveness. The UI Thread utilization graph details the time spent by the UI thread in Parsing, Layout, Render, I/O, Application Code and other framework services. Currently, only Disk I/O is computed in I/O. Network I/O support is slated for a future release. The Visual throughput graph details the frame rate of both the UI thread in the application and the Composition thread in the Desktop Window Manager.
After identifying a region of interest, you can further drill down and filter to the events in the selected time range by click-and-dragging the selection on the graphs. You can achieve more fine grained control over the selected time range by using the left/right arrow keys on the ruler handles.
The details view is where you will be spending most of your time analyzing the report. It shows a detailed view of CPU utilization of your application categorized by the UI Framework subsystem or system component that consumed the CPU. Below is the list of categories and events supported in Visual Studio 2015 CTP 5 for WPF applications. We will continue to enhance this list in the future based on our investigations into real life performance issues and your feedback.
XAML: Layout, Parsing, Render
System: Disk, Network
Other: Garbage Collection
Most of the events occur on the UI thread and are marked as such by the purple bar on the left of the event in the details view. Some of these events have descriptors in their names that enable you to quickly inspect the key property of the event. E.g., the Layout event always shows the number of elements that have taken part in that layout pass. Other events like Disk and Network I/O have hint text that details the total data payload of these requests. This enables you to in many cases co-relate the time consumed by the event to the size of the payload serviced in that time range.
These UI enhancements can be turned off by using the View Settings option in the command bar of the details view.
We also support a variety of filtering options for your convenience that you can access from the Filter option in the command bar. These commands enable you to slice and dice the events in the details view to isolate specific events or regions of interest.
When you find an event of interest, you can drill into it further using the following gestures:
- Selecting the event row will display additional details about it in the detail pane. E.g., selecting a Parsing event will show the full path of the XAML file that was parsed.
- Expanding the event row will display its child events. E.g., expanding a Parsing event will show all Parsing events that was generated as a result of the parent parsing event
By default, the timeline is sorted chronologically. If you want to quickly check out the most expensive events in your session, you can do so by changing the sort type to Duration from Start time.
Some of the key scenarios and optimizations that can be done based on their inspection are given below:
Layout: In large applications, often thousands of elements are shown on the screen at the same time. This might result in a low UI frame rate and correspondingly poor application responsiveness. The Layout event accurately determines the cost of laying out each element (i.e. the time spent in Arrange, Measure, Apply Template, Arrange Override and Measure Override) and builds the visual trees that took part in a Layout pass. You can use this visualization to determine which of your logical trees needs pruning, or to evaluate other deferral mechanisms to optimize your layout pass.
Parsing: This event enables you to identify the total time spent by the UI thread in parsing XAML files and creating objects. It also shows you the dependency chain of all the XAML files that was parsed as a result of the root event. This will enable you to identify unnecessary file parsing and object creation in performance sensitive scenarios and optimize them out.
Disk and Network I/O: Frequent disk access and large network payloads on the UI thread might severely impact application responsiveness . Even if some of these I/O accesses happen on a different thread, it might still impact the perceived responsiveness of the application. These events will detail the total payload and time spent servicing the I/O requests. Currently only network requests serviced through the WININET provider is represented here. Support for other providers will be added in a future release.
Application startup: One of the goals we had laid out while designing the profiler was to make it easy for our customers to quickly identify scenarios of interest in the vast trove of session data that is displayed in the tool. In order to do this, we automatically identify scenarios that we believe are of interest to you and generate semantic events for the same. Application Startup is a semantic event that is created by our tool that measures the interval between application launch by the operating system to the time taken for the application to submit the first frame to the Desktop Window Manager. This measurement in essence captures the startup time of your application. You can choose to filter the session details to this specific scenario by executing the filter to event command in the context menu.
This enables you to quickly identify the events that consume the largest blocks of time in this scenario. In the example above, you can see that Layout event consumes the largest block of time. Optimizing layout here will enable faster application startup.
Frame: If you want to view the total time spent in UI frame creation, you can toggle the Group by Frames option in the command bar. This will group the Layout events and related Render events in a UI thread frame to a semantic Frame event.
Application Code: The Application Timeline tool can be used in conjunction with the CPU Usage tool. This enables you to co-relate excessive App Code execution (observed on the UI Thread utilization graph) to user code that was executed during that time period.
Currently only events from the UI thread of the Main Application Window are shown in the tool. We will be adding support for other UI threads in the application in a near future release of Visual Studio.
Tell us more!
We are interested in knowing more about what you think about our tooling investments in the WPF platform and what you would like to see in the Performance and Diagnostics hub going forward. Please send us your feedback through replies to this post, Connect bugs, User Voice requests, the MSDN diagnostics forum or the Send a Smile button inside Visual Studio.
Author: Harikrishna Menon, Program manager, Visual Studio Client Tools Team
Hari is a Program Manager with Microsoft, and works on the Xaml Experiences Team in Visual Studio. He has been with Microsoft for over 6 years, and has shipped multiple versions of Visual Studio working on a variety of XAML platform and tooling experiences spanning different XAML platforms like WPF, Windows Phone and Windows Store.