JIT Compilation and Performance with Native Image Generator
Hay folks,
As a developer I really concern abt performance right... As all u guys know there is a Native Image Generator (Ngen.exe) shipped with .net framework. So when I researching on that I found this article.
Check this out....
Many developers (especially C/C++ developers) are concerned about JIT compilation because the end-user's machine is compiling code on the fly, hurting the application's overall performance. I used to be very concerned about this performance cost as well, but having written, built, and used many managed assemblies for several years now, my experience has been that the performance loss due to JIT compiling is not that great. In fact, I believe that JIT compiling is awesome and is capable of producing code that is more efficient and more optimized than a compiler that produces native CPU instructions. For example:
The JIT compiler knows precisely which CPU the user has installed in their computer causing the JIT compiler to produce native instructions that are specific to the user's machine. When you use an unmanaged compiler, the compiler usually emits code for an Intel Pentium Pro, Pentium II, Pentium III, or Pentium 4 processor.
The JIT compiler knows if the machine has a single CPU or multiple CPUs installed. If a single CPU is installed, certain thread synchronization mechanisms don't have to be employed.
When a method is JIT compiled, the compiler emits the native CPU instructions. Some of these instructions contain memory addresses that refer to variables or methods. By contrast, an unmanaged compiler and linker emit native CPU instructions that contain memory addresses when building the resulting file. This file must contain relocation information; if Windows can't load the file at its preferred base address, then the embedded memory addresses are incorrect and they must be fixed-up by the Windows' loader. Dynamic relocation (rebasing) significantly hurts the load time of unmanaged code.
For these reasons and more, JIT compiled code is poised to be a clear performance winner when compared to unmanaged compilers and linkers. And, of course, Microsoft is working quite hard at improving the CLR and its JIT compiler so that it runs faster, produces more optimized code, and uses memory more efficiently.
These improvements will take time. For developers that can't wait, the .NET Framework redistributable includes a utility called NGen.exe.
By far, the most common way to run NGen.exe is by simply specifying the pathname of an .exe or .dll assembly file (using no command-line switches). When you invoke NGen.exe, it loads the CLR and tells the CLR to load the assembly. NGen.exe then forces the JIT compiler to compile every method's IL code into native CPU instructions. Each method's native method code is then collected and all of the code is emitted into a new file that NGen.exe creates. This new file is placed in a directory (something like C:\Windows\Assembly\NativeImages1_v1.0.3705). NGen.exe could be run as part of the installation process of an assembly.
On the surface, this sounds great! It sounds like you get all the benefits of managed code (garbage collection, verification, type safety, and so on) without all the performance problems of managed code. However, in reality JIT compilation is only a small portion of the performance cost related to managed code.
Meanwhile, there are several potential problems with respect to NGen'd files:
No Intellectual Property Protection. Many people believe that it might be possible to ship NGen’d files without shipping the files containing the original IL code thereby keeping their intellectual property a secret. Unfortunately, this is not possible. At runtime, the CLR requires access to the assembly’s metadata and the NGen’d files do not contain the metadata.
NGen'd Files Can Get Out-Of-Sync. When the CLR loads an NGen'd file it compares a number of attributes about the previously-compile code and the current execution environment. If any of the attributes don't match then the NGen'd file cannot be used and the normal JIT compiler process is used instead.
Poor Administration. NGen'd file are not automatically deleted when an assembly is uninstalled adversely affecting the .NET Framework is easy administration and XCOPY deployment story.
Inferior Load-Time Performance (Rebasing). When Windows loads an NGen’d file, it checks to see if the file loads at its preferred base address. If the file can’t load at its preferred base address, then Windows relocates the file, fixing-up all of the memory address references. This is extremely time consuming because Windows must load the entire file into memory and modify various bytes within the file. For more information about rebasing please see my book: Programming Applications for Microsoft Windows, 4th Edition (Microsoft Press).
Inferior Execution-Time Performance. When compiling code, NGen can’t make as many assumptions about the execution environment as the JIT compiler can. This causes NGen.exe to produce code with a number of memory-reference indirections that aren’t necessary for JIT compiled code.
Ignored NGen'd File in Some Domain Load Scenarios. In brief, assemblies can be loaded in a domain-neutral or non-domain-neutral fashion. NGen.exe produces code that assumes that the only assembly loaded in a domain-neutral fashion is MSCorLib.dll (which contains the definition for Object, Int32, String, and more). If, at runtime, it is the case that other assemblies are loaded in a domain neutral fashion, the CLR cannot use code produced by NGen.exe and will resort to JIT compilation. For ASP.NET applications (Web Forms and XML Web services), strongly-named assemblies are always loaded in a domain-neutral fashion and therefore they gain no performance benefit from having a corresponding NGen’d file.
Due to all the issues listed above, I recommend that NGen.exe only be used for client applications and only when testing shows a measurable difference in load time. In terms of runtime performance NGen.exe will actually hurt performance instead of improve it. Certainly, for server-side applications, NGen.exe makes no sense since only the first client request experiences a performance hit; future client requests run at excellent speed.
Hay this is not over. Here are few addings to Jeffrey Richter article I got from MSDN.
A native image is a file containing compiled processor-specific machine code. Note that the native image that Ngen.exe generates cannot be shared across Application Domains. Therefore, you cannot use Ngen.exe in application scenarios, such as ASP.NET, that require assemblies to be shared across application domains.
Pre-compiling assemblies with Ngen.exe can improve the startup time for applications, because much of the work required to execute code has been done in advance. Therefore, it is more appropriate to use Ngen.exe for client-side applications where you have determined that the CPU cycles consumed by JIT compilation cause slower performance.
Because there are many factors that affect the startup time of an application, you should carefully determine which applications would benefit from the use of Ngen.exe. Experiment by running both a JIT-compiled and a pre-compiled version of a candidate assembly in the environment in which it will be used. This will allow you to compare the startup times for the same assembly executing under different compilation schemes.If Ngen.exe encounters any methods in an assembly that it cannot generate, it excludes them from the native image. When the runtime executes this assembly, it will revert to JIT compilation for the methods that were not included in the native image.
If Ngen.exe encounters any methods in an assembly that it cannot generate, it excludes them from the native image. When the runtime executes this assembly, it will revert to JIT compilation for the methods that were not included in the native image.
When you use Ngen.exe to create a native image of an assembly, the output depends upon the command line options that you specify and certain settings on your computer. These settings include the following:
The version of the .NET Framework.
The CPU type.
The version of the operating system.
The exact identity of the assembly (recompilation changes identity).
The exact identity of all assemblies that the assembly references (recompilation changes identity).
Security factors.
Ngen.exe records this information when it generates a native image. When you execute an assembly, the runtime looks for the native image generated with options and settings that match the computer's current environment. The runtime reverts to JIT compilation of an assembly, if it cannot find a matching native image. The following changes to a computer's settings and environment cause native images to become invalid:
The version of the .NET Framework.
If you apply a patch, QFE, or update to the .NET Framework, all native images that you have created manually using Ngen.exe become invalid. These assemblies will still run, but the runtime will not load the assembly's corresponding native image. You must manually create new native images for these assemblies.
The .NET Framework automatically creates new native images for the .NET Framework libraries that it installs.
The CPU type.
If you upgrade a computer's processor to a new processor family, all native images stored in the native image cache become invalid.
The version of the operating system.
If the version of the operating system running on a computer changes, all native images stored in the native image cache become invalid.
The exact identity of the assembly.
If you recompile an assembly, the assembly's corresponding native image becomes invalid.
The exact identity of any assemblies the assembly references.
If you recompile any of the assemblies that an assembly references, the assembly's corresponding native image becomes invalid.
Security factors.
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home