In the previous post we discussed how we can improve JIT compilation of .net code by using ProfileOptimization for multicore machines in a .net framework 4.5 application. In this post we are going to discuss another CLR area improved in .net framework 4.5. In the next post, we going to discuss the new tools available in Visual Studio 2012 to further improve this. This discussion is about Native Images of assembly, why we need them and how to write better native assemblies.
What are Native Assemblies?
In the last post we discussed that IL code is compiled into Native code by JIT compiler when the process is being run by CLR. So a natural thought could be what if we could do this compilation before hand and generate the native images. We can use this native image when we actually need them in a process. It would be even better if this image could be shared by various application domains. As a matter of fact, native assemblies in .net fulfills this wish list. Not only they support the native image of a specified assembly, they also support creation of native images of other dependent assemblies.
As we know that JIT compiled image of methods is kept in the memory space of the running process, so creating native images upfront would reduce the memory footprint of the process. This compiled image would also be shared by all the processes requesting the same assembly, hence no process need to JIT compile it separately [as they are Windows PE files] and the proceses could share this, improving the overall system performance. Additionally this would improve the startup time of the process. In addition of time saved for JIT compilation, they also don't require any type safety verification.
Native Images Storage
NGEN [Native Image Generator] creates native image of a managed assembly and installs them to Native Image Cache. This is a reserved area in GAC [Global Assembly Cache]. So this might also be treated as a Time Vs Space trade-off where we sacrifice the hard disk space for the gains in the time saved during the process execution.
You should be able to find them in %WinDir%\assembly\NativeImages_RUNTIMEVERSION.
It must be remembered that these directories not visible in Folder explorer. We can check the contents of the folder in command window though.
Life Time of Native Images
Now let us discuss if these native images last forever on the machines and if and when they can be removed form the machine. This is called reclaiming the images. Before .net framework 4.5 and Windows 8, these images can be claimed manually using NGEN Unistall command. The command can be part of application uninstaller package.
The new framework also supports this for the images installed manually on Windows 8 operating system. For the images created automatically can be claimed automatically by the operating system if they haven't been used for a long time creating more free space for the more frequently used stuff on the machine. These are claimed by Native Image Task during the idle time.
User Level Native Images & Application Container level Native Images
For Windows 8 and later versions of the operating system, .net framework 4.5 supports creation of user and application container based native images. So if a machine is shared between different users, the native images can be made to not share between different user profiles.
Deciding IL Vs Native Images
From the above description it seems that NGENing assemblies would always be beneficial as we are bypassing the JIT compilation when the application is running. Is it really so? NGEN.exe is only for assemblies which run in a full trust scenario. If they are referenced in an application running in partial trust then their non-native version is loaded which goes through JIT compilation.
CLR puts the validation of strong named assemby under extra test which are not in GAC. so if our native image is for a strong assembly [not in GAC], we might not get any benefit as the CLR would still touch every page of the assembly which would nullify any gain caused by NGENing the assemblies.
Native Image Generator [NGEN.exe]
.net framework provides NGEN [Native image GENerator] for assembly's native image generation based on the processor architecture based instruction set. Once we have the native image of an assembly, it doesn't need to be JIT compiled when the application is running, improving the performance of the application. Native Image Generator can be launched using Developer Command Prompt in available with Visual Studio 2012 or Windows SDK Command Shell. For Visual Studio 2012, it appears in the start menu as follows:
The tool supports both installing and uninstalling native images from the native image store. The help about NGEN commands can be obtained by using /? switch with the executable as follows:
Deferring Native Image Generation
Native Image generation work can also be deferred up to when machine has some idle time. This is actually done by queuing up the NGENing of an assembly. This is then taken care of by Native Image Service. This is also used to update the native images because of other related dependencies updates including any updates in .net framework. This service can stand multiple machine reboots as it stores its state. Installation scripts can use NGEN.exe to queue up items for Native Image Service for low priority NGENing running with administrator privilege (which is a general requirement for running NGEN.exe for creating native images). The installer first copies the assembly to the application folder and then uses NGEN to queue up item for deferred NGEN using Native Image Service or Native Image Task based on the operating system you are doing the installation.
For Windows 8 onwards, the responsibilty of NGENing the queued up assemblies is taken over by Native Image Task. This task also support the automatic native image generation and reclaim for an assembly. [http://msdn.microsoft.com/en-us/library/hh691779.aspx]. The automatic NGEN is only for assemblies targeting .net framework 4.5 or later, plus it must have been installed in GAC or Windows Store App package. The automatic native image generation is achieved by the .net framework by tracking down the JITing of an assembly. They are queued for NGENing when the machine is idle.
Assembly Probing and native images
We have discussed in the past how we can determnine the assemblies loaded by an application using Fusion Log Viewer, Process Explorer, List DLls and Visual Studio Modules window [http://www.shujaat.net/2012/04/fusion-log-viewer-fuslogvw-for-assembly.html]. We know that these assemblies can be loaded from different locations which are searched in a predefined fashion. An application can go through a list of steps to locate the requested assembly. This is called Assembly Probing. You can find the details of the process here [How the Runtime Locates Assemblies]. We must remember that they require the application to be running in [Full Trust] for .net framework 4.0 onwards. But after .net framework 2.0, these assemblies can be shared across application domains, plus we don't need to individually NGEN assemblies, while doing this, we can also NGEN their dependencies if they are available in assembly manifest.
Native Image Generation Log
.net framework also supports generation of logs for native images generation of assemblies. These logs can be used for troubleshooting any possible issue when needed. The logs are created in the .net framework folder in %WinDir% folder as follows:
It seems that the log for NGEN service is maintained separately. You can see the NGEN service log as well in the above snapshot. The contents of the log are as follows:
The verbosity of the logs can be controlled using HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\NGenLogVerbosity registry entry. The supported values are 1, 2 and 3. The default value is 2 which is also used in the absence of this registry entry.
.net framework 4.5 also caps the size of this log for computer wide [1MB], user [500KB - Win8 only] and app container [100KB - Win8 only] specific native image generation. The details can be found here: [http://msdn.microsoft.com/en-us/library/hh708846.aspx]
MSCORSVW.exe is used to compile the .net assemblies to native images in the background. You might have seen some threads specially discussing and asking question specially about this executable. Actually you can find the executable in the following folder:
The remedy to get rid of this process is to finish all the queued up items waiting for getting compiled as discussed here:[http://blogs.msdn.com/b/davidnotario/archive/2005/04/27/412838.aspx]. Although this is an old post but it should still be valid.
Native Images and Windows App Store Packages
As we discussed before, Windows 8 supports automatic creation of native images for public assemblies. This is actually one of the App certification requirement for a Windows Store App. This is part of performance test, you can find it here: [http://msdn.microsoft.com/en-us/library/windows/apps/jj657973.aspx#performance_test]. We can also opt-out for this automatic native image generation by including nongen.txt file in our App package.
Linking Native Images with IL Assembly Image
[Erez Metula] has an amazing description of how native images are linked by IL assembly images by .net framework [Chapter 8]. The book is available on amazon and rightly deserves the rating. The book was released in November, 2011, so it discusses the features with .net 3.5 SP1 context [.net v4.0 - released: 3,2011]. But most of the stuff is still valid.
Here IL contains the details of the assemblies which have their native images already created in the cache. NI has further details about the native images identified by [MVID].