Application performance is something we hear about all the time. It almost always falls into one of the top three issues when we aggregate all of the feedback channels from .NET developers. While performance has many characteristics, application startup time is something that everyone can easily relate to. With the .NET Framework 4.5 Beta and the “Visual Studio 11” Beta we’re now sharing with you some of the same techniques we’ve successfully used to make the .NET Framework faster. The following post was written by Ashwin Kamath, a program manager on the CLR performance team. –Brandon
With every release of the .NET Framework, the .NET Framework product team looks for new ways to improve the launch performance of desktop applications. We often find opportunities for the .NET Framework to do less work on startup to achieve small performance improvements, but we also look for broader changes. In the .NET Framework 2.0, we created a new technology that significantly decreases the time it takes to read and execute precompiled native images. We have been using this technology on .NET Framework assemblies since, and it has resulted in significant improvements in application launch performance (startup times) for all managed applications. We call this technology managed profile guided optimization (MPGO). In Visual Studio 11 Ultimate Beta, MPGO is available for you to use with your application code, so you can achieve faster application startup times.
In this blog post, I’ll discuss this new performance technology and how you can use it with managed desktop applications.
Update: For the latest information, see Mpgo.exe (Managed Profile Guided Optimization Tool).
.NET Framework Code Compilation Background
.NET Framework assemblies contain intermediate language (IL) byte-code that needs to be compiled to machine code in order to run on a given processor. The .NET Framework provides two options for code compilation: just-in-time (JIT) compilation and precompilation. With JIT compilation, IL code is compiled at run time prior to execution. This approach is very convenient since it happens automatically and only compiles the subset of your application that is actually needed or executed. You can think of precompilation as ahead-of-time compilation. It requires the use of the Native Image Generator (Ngen.exe) on the same machine as the application in order to precompile a set of assemblies. All of the .NET Framework assemblies (for example, System.dll) are typically precompiled.
Precompiled native images typically result in better application launch performance because JIT compilation is no longer necessary. There are also other important benefits, such as a lower working set (memory usage). We recommend that you create precompiled native images for scenarios where application launch performance is critical, typically for larger desktop applications.
The generation of precompiled native images follows the workflow illustrated in the figure below. Invoking the NGen tool to generate native images must occur on the end-user machine (denoted by the blue box). Native images are not included with your application setup package – the application is shipped to end users as IL, and the NGen tool invoked as part of the application setup on the end-user machine to create native images. For more details on NGen, you may want to refer to the MSDN article on NGen.
Figure 1: Workflow for precompiled native image generation
Even Faster Precompiled Native Images
The .NET Framework has been using an innovative technology to further improve the performance of precompiled .NET Framework native images for years. Most managed applications already enjoy the benefits of this technology, by virtue of the .NET Framework using it. For larger applications more performance wins may be gained by adopting this technology, and for these applications, we recommend its use.
We call this technology managed profile guided optimization (MPGO). It can improve the startup and working set (memory usage) of managed applications by optimizing the layout of precompiled native images. In particular, MPGO co-locates frequently used image data within a native image, such that each request for a disk page of image data has a higher density of useful image data for the running program.
As a result, the running program will make fewer disk page requests — often referred to as “page faults” — which will result in improved performance. MPGO provides its greatest benefit on machines with rotational hard disks; however, it is still beneficial to use on customer machines with solid state disks (SSDs).
MPGO is centered on a process called “training.” You use the MPGO tool to launch your application and collect training data. During training, you exercise a variety of representative user scenarios within your application. It is important to not exercise every possible scenario that your application offers, but the most typical ones for your users. The benefit of MPGO will be based on the quality of this training process. So, you should experiment with this process until you determine the set of training scenarios that result in the best performance for your customers.
Training data is stored in a profile (hence the name of the technology), and the profile is stored as a resource within each IL assembly that is trained. This profile is then used by the NGen tool during compilation of each IL assembly, to optimize the layout of precompiled native images that it generates. MPGO can be thought of as providing extra information to NGen in order to generate higher-quality native images.
The generation of training data and precompiled native images follows the workflow illustrated in the figure below. As in Figure 1, red boxes represent artifacts created on the developer machine and blue boxes represent artifacts generated on end-user machines.
Figure 2: Workflow for optimized precompiled native image generation
As already stated, both NGen and MPGO are recommended for use with larger desktop applications, because the benefit of precompiled native images is typically seen only when it replaces significant JIT compilation at run time. In addition, these technologies are not recommended for ASP.NET and WCF services, given the dynamic deployment models available for those application types, and because startup is typically less important in those scenarios.
Assuming that you do have a large desktop application that is a candidate for MPGO, we recommend that you start by using NGen and measure the performance improvement. If you measure native image performance and still need additional performance improvements, you can also try using MPGO. The MPGO tool does not support Windows Metro style apps in the .NET Framework 4.5 Beta.
Your customers do not need to have the MPGO tool on their machines. They only need to have the NGen tool, which is included in the .NET Framework 4.5 Beta.
Using the MPGO Tool
The MPGO tool is included with Visual Studio 11 Ultimate Beta. The tool can be found at the following path, after you have installed Visual Studio 11 Ultimate Beta:
C:\program files(x86)\microsoft visual studio 11.0\team tools\performance tools\mpgo.exe
You can experiment with the tool by following these steps:
- Obtain a machine with Visual Studio 11 Ultimate Beta and your application installed.
- Run the MPGO tool (as an administrator) with the necessary parameters:
MPGO -scenario MyLargeApp.exe -AssemblyList *.* -OutDir C:\Optimized\
The optimized IL assemblies are created in the C:\Optimized folder.
- Run the NGen tool (as an administrator) with the necessary parameters for each application DLL:
- Run your application – it will now use the optimized native images.
Update: Please consult MSDN for the updated documentation on MPGO.
In closing, the .NET Framework 4.5 enables a new innovative technology for use with desktop applications, called managed profile guided optimization. This technology is used by the .NET Framework itself to benefit all managed applications, including ASP.NET, WPF, WCF, and Metro style apps. In the case of larger desktop applications, it is worth considering both NGen and MPGO as part of your application launch performance plan.
Have you tried NGen and MPGO? Did you see a startup performance improvement with your application? Were you able to integrate these tools into your existing process? Tell us what you think in the comments and with our other feedback options.