Does the .NET Framework need to be reoptimized after upgrading to a new CPU microarchitecture?
Solution 1:
Short answer
It doesn't need to, as of now.
Long answer
Code that targets the .NET Framework Common Language Runtime (CLR) is known as managed code, and code that doesn't is known as unmanaged.
When compiling to managed code, the compiler translates your source code into Microsoft intermediate language (MSIL), which is a CPU-independent set of instructions that can be efficiently converted to native code.
Before you can run Microsoft intermediate language (MSIL), it must be compiled against the common language runtime to native code for the target machine architecture. The .NET Framework provides two ways to perform this conversion:
A .NET Framework just-in-time (JIT) compiler.
The .NET Framework Native Image Generator (Ngen.exe).
Source: Managed Execution Process
JIT compilation
JIT compilation takes into account the possibility that some code might never be called during execution. Instead of using time and memory to convert all the MSIL in a PE file to native code, it converts the MSIL as needed during execution and stores the resulting native code in memory so that it is accessible for subsequent calls in the context of that process.
Source: Managed Execution Process
While in theory the JIT compiler could take advantage of CPU-specific instructions like AES or AVX, such optimizations haven't been implemented yet. Full AVX support will probably come later with a new release of the .NET runtime that includes RyuJIT, the next-gen JIT compiler which is being developed.
Native images
[The Native Image Generator (Ngen.exe) is a tool that performs an] ahead-of-time compilation [of] MSIL assemblies to native code much like the JIT compiler does. However, the operation of Ngen.exe differs from that of the JIT compiler in three ways:
It performs the conversion from MSIL to native code before running the application instead of while the application is running.
It compiles an entire assembly at a time, instead of one method at a time.
It persists the generated code in the Native Image Cache as a file on disk.
Source: Managed Execution Process
When you use ngen.exe
to create native images, the output depends on multiple factors such as the identity of the assemblies, and the framework version. Until version 1.1 of the .NET Framework, the output was also CPU-dependent:
If you upgrade a computer's processor to a new processor family, all native images stored in the native image cache become invalid.
Source: Native Image Generator (Ngen.exe) Legacy Syntax
Starting with version 2.0, some causes of image invalidation (including the CPU type) have been removed. Additionally, a new /update
switch was added to re-create invalid images. Quoting a blog entry written by David Notario (emphasis mine):
In previous versions of the CLR (1.0 and 1.1), we treated NGEN compilation the same way as we treated JIT compilation, ie , given that we are compiling in the target machine, we should take advantage of it. However, in Whidbey [Visual Studio 2005], this is not the case. We assume a PPro instruction set and generate code as if it was targeting a P4. Why is this? There was a number of reasons:
Increase predictability of .NET redist assemblies (makes our support life easier).
OEMs and other big customers wanted a single image per platform (for servicing, building and managing reasons).
We could have had a command line option to generate platform specific code in
ngen
, but given thatngen
is mainly to provide better working set behavior and that this extra option would complicate some other scenarios, we decided not to go for it.Source: Does the JIT take advantage of my CPU?
In Windows 8 and later, the .NET Framework is able to automatically generate and maintain native images based on usage. The Native Image Task will do all the work in the background whenever needed, and there's no need for manual intervention.
Further reading
- Just-in-time compilation
- Does the JIT take advantage of my CPU?
- NGEN Primer
- Native Image Generation