CLR, startup your engines! - by Alain "Lino" Tadros

By: Lino Tadros

Abstract: The Common Language Runtime is the solid rock on which the .NET Framework was built. From it's many features, we start with one that defines the way CLR starts .NET applications.

CLR, Startup your engines!

A lot of people are having a hard time defining the different pieces that make up .NET applications. The Common Language Runtime is probably the most important part of the .NET framework. At the base level, it is the infrastructure that executes applications, and allows them to interact with the other parts of the Framework. It also provides important capabilities in optimizing, securing, and providing many robust capabilities such as application deployment and side-by-side execution. The CLR resides at the bottom of the whole infrastructure and right above the operating system.

Where did the Kernel, User and GDI operating system modules go? Nowhere, they are still there (for now), except that you, the programmer, don't need to worry about them any more. The .NET framework encapsulates the entire system in easy to use Object Hierarchy built in.

So calling an API function like SetBrush(...) at the GDI level to set the Pen brush is now available as a function of an Object in a specific namespace called System.Drawing, where PEN and BRUSH Objects exist allowing the call to SetBrush on the BRUSH Object. Clean! VCL had that for only 7 years now. The good news is that the Object mentality is now at the bottom level of the system not at a wrapper level.

Lets take a look at a small piece of the CLR, the startup". We will write 2 programs in C# and Delphi for .NET and see how the CLR treats each one from the moment you try to run them till they actually launch and run. You will be amazed on how much stuff goes on before the app runs!


//C# code
using System.Windows.Forms; 
namespace FalafelCode 
{ 
  public class HelloWorld 
  { 
    public static void Main() 
   { 
     MessageBox.Show("Falafel does .NET in C#!"); 
   } 
  } 
}

Save this snippet to a file called HelloWorld.cs


//The delphi equivalent
Program DHelloWorld;
uses
  System.Windows.Forms;
begin
  MessageBox.Show('Falafel does .NET in Delphi!');
end.

Save this snippet of code to a file called DHelloWorld.dpr

Compile the first program in C# above from the command line by typing csc HelloWorld.cs.

Compile the second program in Delphi from the command line by typing dccil DHelloWorld.dpr.

You can now run both programs from the command line by typing the name of each EXE created on your drive. Once you run any of the two, the CLR goes to work way before the application appears launched on the screen.

First, the PE (Portable Executable) header is read to identify that this executable is meant to run utilizing the .NET framework.

Use the Dumpbin or Tdump utilities from the MS SDK or Borland tools to take a look at the PE headers of both executables created by the C# and Delphi for .NET. Some very interesting things to look for:

* In the Optional Header Values section the "Number of Directories" jump to 16 (10 Hex) a lot higher than normal Win32 apps.

* In the Raw Data #1 section, find the letters "BSJB" the initials of the 4 architects that created the CLR, right after that you will find the version of the framework that created the executable then to the rest of the section is all the METADATA of the application.

* Also notice the import section containing the name of the magical DLL that will load the CLR and tells it where to start, as you can see it is requesting the load of MSCOREE.DLL and will point to _CorExeMain. That is the main reason MSCOREE.DLL exists.

Second, a manifest is read to identify all external assemblies that need to be loaded for executing this application (more about manifests in future articles). An Assembly is a compiled and versioned collection of code and metadata that forms an atomic functional unit. All Assemblies contain a Manifest, which contains the Assembly name, version, and locale, has a list of files that form the Assembly, what dependencies the Assembly has, and what features are exported by the Assembly.

 

Third, the CLR reads the metadata of the application to determine what it would take, memory wise, to load the classes defined in the application (It does not allocate anything yet, just running some algorithms). Metadata includes information such as a list of types and resources visible outside the assembly. The manifest also includes information about dependencies, such as the version of the assemblies used when the assembly was built.

The CLR maintains an in-memory representation similar to a v-table from the metadata. The metadata tells the loader all the information it needs to know about a type and where to find it. When the runtime loads a type, it replaces the address of each method in this v-table like structure with a piece of stub code. When, and only when, the method is called, the JIT compiler is invoked on the the JIT compiler is invoked on the method, compiling the method's IL into native X86 assembly code or whatever platform the CLR is running on. This code is cached in memory and the CLR now changes the stub code to point to this native code. So, the next time, the method is referenced, the calls to the method will not invoke the JIT compiler and actually use the cached native code.

Folks, we are not done, remember we don't even have a real executable yet to run on our Windows based machine. We only have a manifest, a PE and some gibberish non-linked code called IL (Intermediate Language) that contains the .NET instructions for the future execution of the code. Now the CLR triggers it's magic weapon, the JITer (Just in Time Assembly Linker) to start linking some of the IL compiled code in our exe and convert it into native code based on the chip set and the OS that it is running under.

Note: JITer links in the startup code of the app but not all the code, the rest of the IL gets converted to assembly on demand when the application starts using that code.

Ok, TIME OUT! I sense some questions coming my way :) like this looks interpreted to me! Actually, NOT. This is COMPILED code that is LINKED at runtime by the JITer.

With that said, remember that having 15 or 20 languages out there running on .NET, they all COMPILE to .NET, but they all share the same linker from the CLR.

Another question: Which HelloWorld is faster (C# or Delphi)? Well, speed is not measured like before in the Win32 bit era. Now because the linker is the same, the execution time will be extremely close between VB.NET, C#, Delphi for .NET etc.... it will slightly vary based on the optimized IL that each compiler will produce, but no more 100 - 200 - 300 times faster benchmarks will be seen in the .NET world.

A third question: Why is this faster than 32bit windows programming? I had the same question. Logic would dictate that introducing a new layer between the OS and the programming platform would slow down performance. Writing C++ or Delphi code in Win32 bit world talking to Kernel, User or GDI takes x amount of time; introducing mscorlib.dll (the main .NET assembly) in between these layers could only make this operation slower (x + y). The truth of the matter is that Microsoft did not fabricate the new .NET platform; it was built from the ground up based on a better architecture, way fast linker technology and extremely efficient opcodes that make the JITer perform in a highly efficient manner.

The JITer also has the advantage of running on the machine where the code will be executed. This means that the JITer can examine metrics like the processor speed and the amount of memory in the machine, and use this to tune the native code. Native compilers do not have this advantage, they must either create code for the general case or the developer has to do a whole bunch of work to tune the compiler and produce several versions.

Write to you later, till then, have fun

About Falafel Software Inc:

Falafel Software is all about making the most of software development technology in order to complete the project on time and on budget with best possible user experience. Falafel Software offers a comprehensive suite of software development solutions ranging from strategy to design to implementation that businesses need in order to realize high returns on their investment.
Falafel Logo

Copyright ) 2003 Alain Tadros, Falafel Software Inc.
ALL RIGHTS RESERVED. NO PART OF THIS DOCUMENT CAN BE COPIED IN ANY FORM WITHOUT THE EXPRESS, WRITTEN CONSENT OF THE AUTHOR.

 


Server Response from: ETNASC03