Quantcast
Channel: : software-engineering
Viewing all articles
Browse latest Browse all 19

Why using NGen on your assemblies may not be as smart as you think

$
0
0

NGen.exe is the native code generator for .NET assemblies and is sometimes used during an application’s installation process. NGen takes the assembly’s IL code and precompiles it into native machine code. In contrast, most .NET assemblies are compiled ‘just in time’, by something understandably called the JIT-compiler, or ‘Jitter’.

This offends the sensibilities of some developers – it seems wasteful to have to JIT-compile an assembly every time it runs. Sometimes developers opt to use NGen within their installation process. Possible motivations include:

  1. Reduce application start-up time
  2. Reduce the size of application’s working set (memory)
  3. Improve runtime performance

It ‘seems obvious’ that using NGen will always improve performance, but of course you’ve already guessed that’s not the case. There are many subtleties in play that probably mean the extra effort and complexity of using NGen just isn’t worth it.

there can be modest performance gains in some very specific situations, but in the round, precompiling to native code provides little or no advantage and in some cases, it actually hurts performance.

Let us examine the motives for using NGen.

Reduce start-up time

This is one area where there can be some modest performance gains. If assemblies can be loaded from native code, then the cost of loading the Jitter and JIT-compiling the assembly can be saved. However, the unit of compilation for the Jitter is the Method, not the Assembly. Each method is compiled the first time it is called. methods that are never called are not compiled. There is certainly an up-front performance hit associated with JIT-compiling, but it is not as great as might be expected and does not all occur immediately on application load. Spread out over the application’s lifetime, the impact of JIT-compiling is not really that great.

Reduce Working Set

Native code assemblies can be loaded into shared address space and can therefore be shared across multiple processes. Provided the CLR is able to use the native code assembly, this can provide a modest win, but again the situation is not straightforward.

Improve Runtime Performance

Although it may seem like there should be better runtime performance (perhaps because there is no need to JIT-compile each method), this is usually not the case. Code compiled by NGen runs about 5% slower than JIT-compiled code. NGen has to make some very generalized assumptions about the execution environment, because it does not know how an assembly will be loaded. The JIT-compiler, on the other hand, knows exactly what the runtime environment is, which process the assembly is being loaded into, and so on. The Jitter can therefore make much smarter optimizations than NGen, the result is that JIT-compiled code executes faster overall. For short running programs there may be a detectable difference, but once the JIT-compiler has compiled each method, any benefit of native code is completely gone.

On top of all that, the CLR may not even use your native code assemblies. Before loading a native code assembly, the CLR checks that various attributes have not changed since compilation. These include:

  • CLR version – changes with patches and service packs
  • CPU type – changes if the CPU is upgraded
  • Windows OS version – changes with service packs
  • Assembly’s Module Version ID (MVID) – changes with recompilation
  • The MVID of any referenced assemblies – changes whenever an assembly is recompiled
  • Security permissions may have been revoked

So there is a fair chance that your native code assembly may not even be used; the CLR will fall back to using the JIT-compiler and your net gain will be zero.

Given the (at best) modest gains achievable from using NGen and the additional complexity it entails, I personally would advise developers not to go there.

Much of the above information is taken from Jeff Richter’s excellent book, CLR Via C# 4th Edition - for deeper information on this and other CLR issues, I refer you there. I would say this book is a must for all C# developers.

  

Viewing all articles
Browse latest Browse all 19

Trending Articles