Creating Native Images
Starting with the Windows 8 operating system, native images can be created automatically by the .NET Framework or manually by developers or administrators. Native images can only be created manually on earlier versions of Windows.
The .NET Framework generates native images automatically by tracking work done by the JIT compiler. Native image creation is too time-consuming to do while the application is running, so the common language runtime (CLR) queues native image generation tasks to execute when Windows schedules maintenance mode. When the native image generation task starts, it creates images for any tracked assemblies. When applications launch after the native images are created, they automatically load the native images instead of compiling Microsoft intermediate language (MSIL) with the JIT compiler.
Automatic native image creation is available on all Windows Client SKUs starting with Windows 8. An assembly is eligible for automatic native image creation if it meets the following criteria:
The assembly targets the .NET Framework 4.5 or later.
The assembly is installed in a supported location:
The global assembly cache.
A Windows Store app package.
The .NET Framework automatically manages the tracking, creation, and reclamation of these native images. For information about the automatic reclamation of native images, see Reclaiming Native Images.
Because the .NET Framework generates native images automatically based on usage, the first time an assembly is loaded it is compiled by the JIT compiler. Native images are generated later, when Windows schedules maintenance mode. If you want to get native images for your app sooner (for example, for testing purposes), you can run your app, close it, and run the NGen Task using the Windows Task Scheduler.
Developers who work in scenarios where automatic native image creation is not supported can still benefit from native images by using Ngen.exe (Native Image Generator) to manage the native image cache. NGen.exe can be used from any process that has administrator privileges, but is typically launched during application installation. The installation script first copies assemblies to their installation location, and then calls NGen.exe with the install command to create the native images for all the application's assemblies.
When you call NGen.exe during setup, it is often beneficial to defer compilation. Installations that defer compilation let users run their application without waiting for native image compilation to complete, which can be time-consuming for a large assembly. The user’s first run experience uses the JIT compiler instead of native images. The next time Windows schedules maintenance mode, the Native Image Task generates the requested native images. The next time the application is launched, it uses the newly generated images.
To ensure a good experience during the interval between installation and the next time automatic image generation can occur, you can use multicore background JIT to speed up critical code. See the ProfileOptimization class.
Native images can be created immediately, or asynchronously by the Native Image Task or the Native Image Service. Many applications defer native image creation because it shortens the installation process and enables the user to use the application sooner. Deferred image generation also enables NGen.exe to utilize multiple CPU cores, reduces the time required to generate native images, and allows greater flexibility in the timing of native image creation.
The first step in creating native images asynchronously is to pause the worker process. This ensures that the worker process does not try to compile an assembly before the assembly is copied to disk. The following Ngen.exe command pauses the service in preparation for queuing the creation of new images:
ngen queue pause
Owners of shared assemblies must make sure that native images for dependent assemblies stay up to date. The following Ngen.exe command lines install a native image for a shared component and perform an update of all roots that may be affected.
ngen install "c:\Program Files\MyComponent\SharedAssembly.dll" /queue ngen update /queue
The first line registers an assembly for asynchronous compilation. In this case, the compilation target is specified by using a fully qualified path to the assembly. Because /queue is specified, the NGen worker compiles the assembly asynchronously.
Because SharedAssembly.dll is intended to be shared across applications, NGen.exe needs to look for and update any native images that depend on this assembly. The second line tells the NGen worker to asynchronously recompile any assembly whose dependency has changed.
An installer for a shared assembly should always assume that dependent assemblies have already been compiled by NGen.exe, even if the shared assembly is being installed for the first time. If NGen.exe finds that an assembly’s dependency is missing, it will generate a native image that is usable only when the dependency is not available. If a native image for the shared assembly is installed later, the dependent assembly’s native image must be regenerated; otherwise, it will not use the shared assembly's native image.
The following command generates a native image for ClientApp.exe, located in the current directory, and installs the image in the native image cache. If a configuration file exists for the assembly, Ngen.exe uses it. In addition, native images are generated for any .dll files that ClientApp.exe references.
ngen install ClientApp.exe
An image installed with Ngen.exe is also called a root. A root can be an application or a shared component.
The following command generates a native image for MyAssembly.exe with the specified path.
ngen install c:\myfiles\MyAssembly.exe
When locating assemblies and their dependencies, Ngen.exe uses the same probing logic used by the common language runtime. By default, the directory that contains ClientApp.exe is used as the application base directory, and all assembly probing begins in this directory. You can override this behavior by using the /AppBase option.
An assembly can have a dependency without a reference, for example, if it loads a .dll file by using the Assembly.Load method. You can create a native image for such a .dll file by using configuration information for the application assembly with the /ExeConfig option. The following command generates a native image for MyLib.dll by using the configuration information from MyApp.exe.
ngen install c:\myfiles\MyLib.dll /ExeConfig:c:\myapps\MyApp.exe
Assemblies installed in this way are not removed when the application is removed.
To uninstall a dependency, use the same command-line options that were used to install it. The following command uninstalls MyLib.dll from the previous example.
ngen uninstall c:\myfiles\MyLib.dll /ExeConfig:c:\myapps\MyApp.exe
To create a native image for an assembly in the global assembly cache, use the display name of the assembly; for example:
ngen install "ClientApp, Version=126.96.36.199, Culture=neutral, PublicKeyToken=3c7ba247adcd2081, processorArchitecture=MSIL"
NGen.exe generates a separate set of images for each scenario you install. For example, the following commands install a complete set of native images for normal operation, another complete set for debugging, and a third for profiling:
ngen install MyApp.exe ngen install MyApp.exe /debug ngen install MyApp.exe /profile
If your application consists of many roots, you might have to control the priority of the deferred actions. The following commands queue the installation of three roots. Assembly1 is installed first, without waiting for Windows to schedule maintenance mode. Assembly2 is also installed without waiting for maintenance mode, but after all priority 1 actions have completed. Assembly3 is installed when Windows schedules maintenance mode.
ngen install Assembly1 /queue:1 ngen install Assembly2 /queue:2 ngen install Assembly3 /queue:3
When all deferred operations have been queued, the following command allows the worker to resume:
ngen queue continue
When all work is scheduled and the NGen worker has resumed, the application can either inform the user of success immediately, leaving NGen to schedule the creation of native images, or it can wait for some native images to be created. For example, some applications depend on their high-priority native images to be created before the user runs the application for the first time. You can force queued actions to occur synchronously by using the executeQueuedItems action. If you supply the optional priority, this action affects only the queued actions that have equal or lower priority. The following command causes the native image task to complete all work that is queued with priority 2 or higher. Priority 3 work will be completed when Windows schedules maintenance mode:
ngen executeQueuedItems 2
Another approach to synchronously creating native images to run the NGen Install command without the /queue option. We do not recommend this approach, because it does not allow NGen.exe to use asynchronous optimizations, such as executing on multiple processors.