Trying to understand the basics of C# and .NET
Hello guys, sorry to disturb you all; I'm current learning C#l; I just started so I'm trying to understand some basic things first.
From what I have understood, C# is a programming language built on top of the .NET framework. C# is widely used because of its libraries/community support which help in the development of games, web services, desktop app etc... (please correct me if I'm wrong). Now when we run a C# code, our code isn't directly run/translated into machine code.
What happens, is at runtime (when we run the code), our source code is compiled into an intermediate language (in java I know we refer it to as bytecode, here what is its technical name please). This compilation is done by a virtual machine known as the CLR, common language runtime virtual machine. After compilation, this intermediate code is then translated into machine code and executed.
This make C# platform independent meaning we can run it on any OS we want.
Now I have came across 2 things, the Garbage collector and Just-In Time Compilation (JIT). I know that Garbage collector is that "free" memory (RAM) when required. But what about the JIT please; what is its use, why is it useful. I don't have a good understanding of JIT, would really appreciate if someone can explain pls.
31 Replies
You're mostly correct, but some stuff got mixed up which causes the confusion.
C# is a compiled language, but it compiles to IL (intermediate language). This is NOT at runtime, this is at compiletime.
The JIT runs at runtime and compiles the IL to actual machinecode as it runs, and it can even compile the same thing several times (with different degrees of optimization when it detects a hot path etc).
hmm compile time is when our source code is converted into IL ? Run time is when the IL is converted into Machine code? or when the machine code is executed pls
runtime is both JIT and execution of the produced machine code
ie, the dotnet runtime tries to run the IL, sees that it needs to use the JIT to produce the machine code, does so, then executes it
the second time it hits the same instruction, the machine code is already done and ready to use. It can however decide to try and generate BETTER machinecode, if it detects that this instruction runs very often
oh okay
so the code does change, well the machine code I mean
if necessary
yeah, it can
yep I see, interesting
I think I have a clearer understanding now, really appreciate, thanks !!
C# also supports AOT (ahead of time) compilation, which removes the need for JIT AND the need for a runtime
I have questions on how AOT and JIT compilation works, I will just create another post (well I need someone to clarify if my understanding is correct xd)
but some features are disabled in this compilation mode
hmm what do you mean that it removes the need for a runtime pls
can I just post my question on AOT vs JIT here or I should open another post?
well the .NET runtime is what controls the entire JIT -> Machinecode process, and running that code
but if you use AOT, your compiled program isnt IL, its native machine code
so no runtime needed
ah
you can ask here
runtime is needed only when their is IL related to it?
just to be clear, "runtime" can mean 2 things
1. the .NET runtime, a program that needs to be installed on any computer to run compiled .NET programs
2. "run-time", meaning when the program is executing
ahh
I think I was confused 2sec
for example, look here https://dotnet.microsoft.com/en-us/download/dotnet/9.0
ok so the .NET runtime is the thing that "execute" the intermediate language ?
there are runtimes on the right side
yes
sorta
and how it executes it is by using JIT, then executing the resulting machine code
yepp I see
Can you just have a look at the following statements and correct me if I'm wrong or add up to it pls:
I was just reading a bit about AOT and JIT Compilation. Can someone clarify/add to from what I have understood pls:
JIT Compilation
JIT Compilation works by compiling intermdiate code / bytecode into machine code so that we don't re-compile and execute similar block of code over and over. In other words, repeated block of code is what the JIT compiler targers to improve efficiency. For e.g, if we loop 1000 times, we don't want to re-compile and execute this re-compiled code 1000 times but instead what we want for efficiency is that compiled this repeated code once (also known as hot code), then store it in memory so that each time we loop, we directly access the machine code implementation of the intermediate code and we execute directly thus improving execution time.
So, using a JIT compiler, what happens is that chunks of intermediate codes is converted into machine code and stored in memory and the machine code is fetched each time me need it.
AOT Compilation
I didn't go in depth in AOT compilation but from what I have understood, AOT would compile the entire intermediate code all at once into machine code. This would normally create a separate file, like the
.exe
file and this file is the one which would get executed. We don't re-compile things multiple time, this is done only once.JIT Compilation works by compiling intermdiate code / bytecode into machine code so that we don't re-compile and execute similar block of code over and over.not sure how the first part relates to the second part? using IL/bytecode doesnt prevent execution of the same code
In other words, repeated block of code is what the JIT compiler targers to improve efficiency.not in other words, but yes - a JIT compiler has the ability to re-write parts of a program during execution. This is a major feature of JIT.
yep I mean, we don't re-compile and execute because it would takes more time rather than just executing an already existing machine code
For e.g, if we loop 1000 times, we don't want to re-compile and execute this re-compiled code 1000 times but instead what we want for efficiency is that compiled this repeated code once (also known as hot code)Well, it will first be compiled once using the "naive" approach. When the runtime detects that this particlar branch is run a lot, it will ask the JIT to do it again, but with more aggressive optimizations. this can happen in several steps like, naive -> better -> even better -> best
yep this is what you mentioned earlier
yes
then store it in memory so that each time we loop, we directly access the machine code implementation of the intermediate code and we execute directly thus improving execution time.correct
I didn't go in depth in AOT compilation but from what I have understood, AOT would compile the entire intermediate code all at once into machine code.not really. There is no separate IL in AOT compilation, its source -> native. I do believe that how the AOT is actually implemented it does generate IL - but thats an implementation detail and not a requirement. you absolutely could write an AOT compiler that doesnt use IL
We don't re-compile things multiple time, this is done only once.correct.
yep I see
I believed I have a clearer understandings of how JIT, AOT and the .NET runtime work, thanks, really appreciate, was very insightful 👍
np
if you have even more technical questions, #roslyn is a great channel with people from the actual C# compiler team present
Alright, noted ! Thanks !
but its never wrong to open a thread here either 🙂
😂 yep got it