Improving startup performance with NGen
EF6 Onwards Only - The features, APIs, etc. discussed in this page were introduced in Entity Framework 6. If you are using an earlier version, some or all of the information does not apply.
The .NET Framework supports the generation of native images for managed applications and libraries as a way to help applications start faster and also in some cases use less memory. Native images are created by translating managed code assemblies into files containing native machine instructions before the application is executed, relieving the .NET JIT (Just-In-Time) compiler from having to generate the native instructions at application runtime.
Prior to version 6, the EF runtime’s core libraries were part of the .NET Framework and native images were generated automatically for them. Starting with version 6 the whole EF runtime has been combined into the EntityFramework NuGet package. Native images have to now be generated using the NGen.exe command line tool to obtain similar results.
Empirical observations show that native images of the EF runtime assemblies can cut between 1 and 3 seconds of application startup time.
How to use NGen.exe
The most basic function of the NGen.exe tool is to “install” (that is, to create and persist to disk) native images for an assembly and all its direct dependencies. Here is how you can achieve that:
- Open a Command Prompt window as an administrator
- Change the current working directory to the location of the assemblies you want to generate native images for:
cd <*Assemblies location*>
Depending on your operating system and the application’s configuration you might need to generate native images for 32 bit architecture, 64 bit architecture or for both.
For 32 bit run:
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install <Assembly name>
For 64 bit run:
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install <Assembly name>
Generating native images for the wrong architecture is a very common mistake. When in doubt you can simply generate native images for all the architectures that apply to the operating system installed in the machine.
NGen.exe also supports other functions such as uninstalling and displaying the installed native images, queuing the generation of multiple images, etc. For more details of usage read the NGen.exe documentation.
When to use NGen.exe
When it comes to decide which assemblies to generate native images for in an application based on EF version 6 or greater, you should consider the following options:
- The main EF runtime assembly, EntityFramework.dll: A typical EF based application executes a significant amount of code from this assembly on startup or on its first access to the database. Consequently, creating native images of this assembly will produce the biggest gains in startup performance.
- Any EF provider assembly used by your application: Startup time can also benefit slightly from generating native images of these. For example, if the application uses the EF provider for SQL Server you will want to generate a native image for EntityFramework.SqlServer.dll.
- Your application’s assemblies and other dependencies: The NGen.exe documentation covers general criteria for choosing which assemblies to generate native images for and the impact of native images on security, advanced options such as “hard binding”, scenarios such as using native images in debugging and profiling scenarios, etc.
Make sure you carefully measure the impact of using native images on both the startup performance and the overall performance of your application and compare them against actual requirements. While native images will generally help improve startup up performance and in some cases reduce memory usage, not all scenarios will benefit equally. For instance, on steady state execution (that is, once all the methods being used by the application have been invoked at least once) code generated by the JIT compiler can in fact yield slightly better performance than native images.
Using NGen.exe in a development machine
During development the .NET JIT compiler will offer the best overall tradeoff for code that is changing frequently. Generating native images for compiled dependencies such as the EF runtime assemblies can help accelerate development and testing by cutting a few seconds out at the beginning of each execution.
A good place to find the EF runtime assemblies is the NuGet package location for the solution. For example, for an application using EF 6.0.2 with SQL Server and targeting .NET 4.5 or greater you can type the following in a Command Prompt window (remember to open it as an administrator):
cd <Solution directory>\packages\EntityFramework.6.0.2\lib\net45 %WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install EntityFramework.SqlServer.dll %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install EntityFramework.SqlServer.dll
This takes advantage of the fact that installing the native images for EF provider for SQL Server will also by default install the native images for the main EF runtime assembly. This works because NGen.exe can detect that EntityFramework.dll is a direct dependency of the EntityFramework.SqlServer.dll assembly located in the same directory.
Creating native images during setup
The WiX Toolkit supports queuing the generation of native images for managed assemblies during setup, as explained in this how-to guide. Another alternative is to create a custom setup task that execute the NGen.exe command.
Verifying that native images are being used for EF
You can verify that a specific application is using a native assembly by looking for loaded assemblies that have the extension “.ni.dll” or “.ni.exe”. For example, a native image for the EF’s main runtime assembly will be called EntityFramework.ni.dll. An easy way to inspect the loaded .NET assemblies of a process is to use Process Explorer.
Other things to be aware of
Creating a native image of an assembly should not be confused with registering the assembly in the GAC (Global Assembly Cache). NGen.exe allows creating images of assemblies that are not in the GAC, and in fact, multiple applications that use a specific version of EF can share the same native image. While Windows 8 can automatically create native images for assemblies placed in the GAC, the EF runtime is optimized to be deployed alongside your application and we do not recommend registering it in the GAC as this has a negative impact on assembly resolution and servicing your applications among other aspects.