I am running performance profile for a C# application on a virtual machine.
The results shows a huge load of "JIT Compiler". When I dig further, it shows something called "Class Loader" as the only method getting called by JIT compiler.
What should I do to bring "JIT compiler" load down?
JIT is the 'Just In Time' compiler, this essentially compiles your C# into executable code that can work on the current processor.
.Net comes with a utility called NGEN, this creates a native image of your C# code, that doesn't need to be JIT'ted. There are downsides to this however, have a read of this:
http://codeidol.com/csharp/net-framework/Assemblies,-Loading,-and-Deployment/Native-Image-Generation-%28NGen%29/
And finally here's a link to the MS info about NGEN:
http://msdn.microsoft.com/en-us/library/6t9t5wcf%28VS.80%29.aspx
You could try using NGEN to pre-JIT your assemblies to native images. This will lessen Jitting overhead on application load:
http://msdn.microsoft.com/en-us/library/6t9t5wcf(VS.80).aspx
You should run this tool on the machine where your assemblies are i.e. your virtual machine.
Related
Its very basic question.
JIT compilation is on demand as per MSDN MSIL To Native Code.
Every time when we run the assembly JIT compiler converts MSIL to Native language? Or When we run assembly first time, it converts and store the native language code to somewhere?
Thanks in advance!
The JIT compiler compiles your code when you start the application and stores it in memory.
This code can be cached by ngen.exe (Native Image Generator) and stored in the native image cache. This will be automatically loaded the next time you start the application, and you won't have to JIT the MSIL code a second time.
Ngen.exe creates native images, which are files containing compiled processor-specific machine code, and installs them into the native image cache on the local computer. The runtime can use native images from the cache instead of using the just-in-time (JIT) compiler to compile the original assembly.
The native image cache can be found on a path similar to C:\Windows\assembly\NativeImages_v4.0.30319_64. This path is not accessible through Windows Explorer, so use cmd or a powershell.
I am trying to get something clarified.
When a .NET console application is run, does mscorlib.dll/mscoree.dll get loaded in the process's virtual address space?
mscorlib.dll and mscoree.dll (CLR) are not managed dlls. Is that correct?
Also, what is a good resource to understand more about how a .NET program is executed?
Yes. You'll always get mscoree.dll loaded, that's the bootstrapper for the default CLR host. It is an unmanaged DLL. Every .NET assembly contains a wee bit of native code, just a jump into that DLL. It does however get loaded by recent Windows versions directly, the OS loader has .NET awareness built-in. You can see it in the Debug + Modules window when you turn on the unmanaged debugging option, Project + Properties, Debug tab. You'll then also see mscorjit.dll, mscorwks.dll and msvcr80.dll, three other chunks of native code that are required to run managed code. Respectively the just-in-time compiler, the CLR and the C-runtime support library. They have different DLL names in .NET 4.
Technically it is possible to not get mscorlib.dll loaded, the compiler has the /nostdlib option to avoid a reference to that assembly. Practically that only works if you provide a substitute, that's how Silverlight gets compiled for example. It is otherwise a mixed-mode assembly with some native code but mostly managed code. There's a separate version of it for the 64-bit framework because of that. You'll also see mscorlib.ni.dll with unmanaged debugging enabled, that's the ngen-ed version of the assembly.
I would recommend to read the Jefrey Richter's book CLR via C#. It provides very clear explanation what is going on under the hood :)
Also yoг may find this question helpful: Why is an assembly .exe file?
.Net Executable is no different than any other PE files. So like every imported dlls in native executable, mscorlib.dll is loaded in the Process virtual space of .net executable.
If it interests you, you can read about PE file format here
I am curious to know what the disadvantage is by calling Assembly.Load(AssemblyName) numerous times with the same version of assembly. Does the runtime know not to load the assembly again after the first call? If not, is there any way to detect what's already loaded?
Thanks in advance.
When you use this overload it will be loaded only once in memory. You can verify it with Process Explorer. Look at the loaded modules list. Every assembly is loaded up to .NET 3.5 with LoadLibrary. Additionally it is loaded as memory mapped file into the process.
Starting with .NET 4.0 an assembly is loaded only as memory mapped file and not via LoadLibrary anymore except if it is a precompiled ngenned assembly.
This breaking change in .NET 4 was done because MS found during the development of VS 2010 that their memory did deplete rather quickly. Somebody found that every loaded assembly cosumed twice its original size in virtual memory because it was loaded once via LoadLibrary and a second time as memory mapped file. This is not easy to find except if you look with VMMap into your process. Due to the massive amount of code in VS this was a major issue for VS2010 which is now mostly managed.
Q1) Why is C# initially compiled to IL and then at runtime JIT complied and run on top of a virtual machine(?). Or is it JIT complied to native machine code?
Q2) If the second is true (JIT complied to native machine code), then where is the .NET sandbox the code runs under?
Q3) In addition, why is the code compiled to IL in the first place. Why not simply compile to native machine code all the time? There is a tool from MS from this called ngen but why is that optional?
The IL is JIT'd (JIT = Just In Time) compiled to native machine code as the process runs.
The use of a virtual machine layer allows .NET to behave in a consistent manner across platforms (e.g. an int is always 32 bits regardless of whether you're running on a 32- or 64- bit machine, this is not the case with C++).
JIT compiling allows optimisations to dynamically tailor themselves to the code as it runs (e.g. apply more aggressive optimisations to bits of code that are called frequently, or make use of hardware instructions available on the specific machine like SSE2) which you can't do with a static compiler.
A1) JIT compiles to native machine code
A2) In .net there is no such term as sandbox. There is AppDomains instead. And they runs as part of CLR (i.e. as part of executable process)
A3) NGen drawbacks from Jeffrey Richter:
NGen'd files can get out of sync.
When the CLR loads an NGen'd file, it compares a
number of characteristics about the previously compiled code and the current execution
environment. If any of the characteristics don't match, the NGen'd file cannot be
used, and the normal JIT compiler process is used instead.
Inferior Load-Time Performance (Rebasing/Binding).
Assembly files are standard Windows PE files, and, as such, each contains a preferred base address. Many Windows
developers are familiar with the issues surrounding base addresses and rebasing. When JIT compiling code, these issues aren't a concern because correct memory address references are calculated at run time.
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 inferior code. For example, NGen won't optimize the use of
certain CPU instructions; it adds indirections for static field access because the actual
address of the static fields isn't known until run time. NGen inserts code to call class
constructors everywhere because it doesn't know the order in which the code will execute
and if a class constructor has already been called.
You can use NGEN to create native versions of your .NET assemblies. Doing this means that the JIT does not have to do this at runtime.
.NET is compiled to IL first and then to native since the JIT was designed to optimize IL code for the current CPU the code is running under.
.NET code is compiled to IL for compatability. Since you can create code using C#, VB.NET, etc then the JIT needs a common instruction set (IL) in order to compile to native code. If the JIT had to be aware of languages, then the JIT would need to be updated when a new .NET language was released.
I'm not sure about the sandbox question, my best guess is that a .NET app runs with 3 application domains. One domain contains the .NET runtimes (mscorlib, system.dll, etc), another domain contains your .NET code, and I can't recall what the other domain's for.
Check out http://my.safaribooksonline.com/9780321584090
1. C# is compiled in to CIL (or IL) because it shares a platform with the rest of the .NET languages (which is why you can write a DLL in C# and use it in VB.NET or F# without hassle). The CLR will then JIT Compile the code into Native Machine Code.
.NET can also be run on multiple platforms (Mono on *NIX and OS X). If C# compiled to native code, this wouldn't be nearly as easy.
2. There is no sandbox.
3. Covered in the answer to #1
A1) This way it's platform agnostic (Windows, Linux, Mac) and it can also use specific optimizations for your current hardware. When it gets JIT compiled it's to machine code.
A2) The whole framework (the .NET framework) is all sandbox so all calls you might make through your app will go through the .NET framework sandbox.
A3) As in answer 1, it allows the .NET binary to work in different platforms and perform specific optimizations in the client machine on the fly.
Compiled .Net code becomes IL which is an intermediate language in the exact same way as that of Javas' object code. Yes it is possible to generate native machine code using the NGen tool. NGen binds the resulting native image to the machine, so copying the ngen'd binary to a different system would not produce expected results. Compiling to intermediate code allows for runtime decisions that can be made that otherwise can't (easily) be made with a staticly-typed language like C++, it also allows the functioning of code on different hardware archetectures because the code then becomes descriptive in the sense that it also describes the intent of what should happen in a bit (eg 32 or 64)-agnostic way, as opposed to machine-specific code that only works on 32-bit systems or 64-bit systems but not both.
Also, NGen is optional because as I said it binds the binary to the system, it can be useful when you need the performance of compiled machine code with the flexibility of a dynamically typed language and you know that the binary won't be moving to a system it's not bound to.
When you write an application in C#, and then run it, will it not be compiled again next time it's run, or everything that's used is gonna be recompiled every time the application starts up?
How does JIT compiling works for caching?
For any DLL that is not in the ngen'd, every time you run the application, it will re-JIT the code that is used. There is no caching of the JIT code in between runs of the same non-ngen'd DLL.
EDIT Cleared up a mistake with GAC and NGEN