The code compilation process in .NET

In this post, I’m going to explain how the compilation process in .NET happens. I will cover the different types of compilations and compilers.

Overview

.NET is Microsoft’s open-source software development platform. It includes a variety of tools used for creating software applications. You can develop web, mobile, desktop applications, IoT, and a lot more with one of the three supported languages in the platform โ€“ C#, F#, or Visual Basic. Overall, you can think of .NET as a platform with two main components:

  • A huge library for developing applications on different platforms, with any of the supported languages.
  • Apart from just being a library, .NET contains another important component called Common Language Runtime, or CLR. This is the virtual machine that manages the program execution, written in any language supported by .NET. It is the heart and the runtime environment of any .NET program. CLR is doing the magic for running a .NET application and provides a lot of services, that make the development process easier. One of the most important CLR jobs is compilation.

Types of compilation

We know that modern languages provide human-readable syntax for writing code. However, the computer doesnโ€™t understand this syntax, so the code must be converted into something clear to the machine. This process is called compilation and can be done explicitly or implicitly.

Implicit compilation (JIT Compilation)

When you write a program in any one of the supported .NET languages, you must compile it to work on the machine environment. Here is what is happening under the hood:

  • First of all, the CLR triggers a language-specific compiler to do the job. For C# and VB, the compiler is Roslyn. For F#, another compiler is available because of some language specifics.
  • This language-specific compiler aims to transform the code into something called Microsoft Intermediate Language (MSIL), Common Intermediate Language (CIL), or just IL.
  • The output of this a portable execution file is .exe or .dll. The compiler stores as metadata in this file information about the environment, programming language, class libraries, and any other information, needed for the CLR to handle it.
  • When you run the program, the CLR calls another compiler called Just In Time (JTI) compiler, which will compile the code into native code, for the current machine based on the metadata, stored by the language-specific compiler. The JIT compiler knows how to interpret the IL to successfully turn it into native code. The JIT compiler in .NET is RyuJIT.
Compilation process in .NET
Compilation process in .NET

Types of JIT Compilers

There are 3 types of JIT compilers:

  • Pre-JIT Compiler โ€“ all the code is compiled into native code in a single compilation cycle. This compiler in .NET is executed through the โ€œNgen.exeโ€ process.
Pre-JIT Compiler
Pre-JIT Compiler
  • Normal JIT Compiler โ€“ Compiles only the methods that are called at runtime. After execution, these methods are stored in a memory cache, from where they are used, if called again
Normal JIT Compiler
Normal JIT Compiler
  • Econo JIT Compiler โ€“ Similar to the normal JIT compiler, but instead of caching methods, they are removed after usage. Starting with .NET 2.0, the compiler is deprecated.

Explicit compilation (Ahead of Time compilation)

This is one level process, also called Ahead of Time compilation or just AOT. Human-readable code is directly translated into native code without running through the IL process. The difference is that the JIT compiler, compiles the problem from IL to native code as it is running, but the AOT compilation compiles it before it is running.

JIT vs AOT Compilation Pros and Cons

What are the advantages and disadvantages of the two methods:

JIT compilers can usually generate faster code than the AOT, because it has the exact information for the current machine where the program is running, at the time of the compilation. With AOT you have the native code compiled in the first place, and you must use this version on all machines you want to run the program. Having all the machine information, the JIT can create optimizations in your program, based on the current machine CPU for example. On the other hand, the AOT compilation will be faster for large applications, whereas the JIT will be slow doing its optimizations for a lot of code. Another great benefit of the JIT is that it can profile and dynamically re-compile the application, while it runs if needed. Usually, it tries to optimize the most used function in the code.

Compilation process in .NET - JIT vs AOT Compilation Pros and Cons
Compilation process in .NET – JIT vs AOT Compilation Pros and Cons