C#, Assembiles and JITing

The last few days I ve been doing more C# than anything else. Never thought it would come to this! So heres my first post on some notes I ve taken.
In .NET an assembly is a reusable, self-describing, versionable deployment unit for types and resources. Because it is self-describing, it allows the .NET runtime to fully understand the application and enforce dependency and versioning rules. Unlike Java—in which both a stand-alone application and a component library are deployed as a .jar file—assemblies come in four types or formats and essentially consist of a manifest that contains the assembly metadata, one or more modules and other resource files such as icons etc.
  • exe. A console executable. The application must contain one entry point defined in the Main method. There is also a tool called the MSIL Disassembler ( Ildasm.exe ) which is a counterpart of the MSIL Assembler (Ilasm.exe) which takes the portable executable (PE) file that contains Microsoft intermediate language (MSIL) code and creates a text file suitable as input to Ilasm.exe. - talk about round trip decompilation?
  • Library. A library (DLL) that can be used by other assemblies.
  • Module. A nonexecutable collection of compiled code for use in other assemblies.
  • winexe. A graphical Windows executable. The assembly must contain one entry point.
Programmatically a .NET assembly is represented by the Assembly class of the System.Reflection namespace and can be programmatically used to query the assembly. Eg Assembly asm = Assembly.LoadFrom("WSTest.exe");

Another concept similar to Java is that of shared asseblys (just like Jars are shared in an app server) . But .NET does not have the concept of class loaders or class paths so the CLR looks in only once place - the Global Assembly Cache (GAC) which is really a directory (usually %Systemroot%\\assembly or %Systemroot%\\assembly) where the CLR can locate such shared assemblies. There is a tool called the GAC tool (gacutil.exe) to install shared assemblies in the GAC. To share an assembly requires it to have globally unique name (aka a strong name) which consists of the name, version information, culture information, and a public key for cryptography. To create a public key, the .NET Framework provides a strong name tool called sn.exe, which creates a key file that can be referenced in the AssemblyInfo.cs. For my example I used sn–k WSTest.snk and created an Assembly.cs that contained something like

using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("WSTest")]
[assembly: AssemblyDescription("WSTest app ")]
[assembly: AssemblyCompany("Sun Microsystems")]
[assembly: AssemblyProduct("WSTest")]
[assembly: AssemblyCopyright("This is the property of Sun Microsystems ")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("")]
[assembly: AssemblyKeyFile("WSTest.snk")]

Now to create the WSTest.dll with with a strong name: csc /target:library /out:WSTest.dll WStest.cs AssemblyInfo.cs and then stored it in the GAC using gacutil /i WSTest.dll
Boom ! We have a shared assembly. So whats the idea - well the plan was to JIT it up and see what happenes with performance.
Theres a bunch of detail on the MSDN website about how runtime objects are created and another link on pros/cons of JIT'ing Essentially when a reference to an object is first encountered, the JITer loads a stub for each method that matches that method's declaration.When the same method is later invoked, the IL for it is compiled and the stub is replaced with the address of the method's compiled code. This happens each time a method is invoked for the first time, and the resulting native code is cached so that it can be reused the next time the assembly is loaded during that session. The JIT compiled code is not actually stored on disk and reused for subsequent executions of the same application. This actually can be done if needed with what Microsoft calls the Native Image Generator - Ngen.exe that a pre-compiles (pre-JIT) IL application code into native machine language code after installation. . A quick peek inside teh C:\\WINNT\\assembly folder shows that not all shared assemblys are in fact JIT compiled to native code. (see x86 and MSIL as proc arch) . The reason is apparently that JIT performs lots of on-the-fly optimizations when compiling MSIL. Many of these optimizations, particularly those involving the use of registers and memory, are driven by the current demands made on the system. Compiling assemblies in one large batch prevents these optimizations from being made and therefore may actually result in slower final code for the server side execution.

Hmm....Did'nt we do this five or more years back with the JDK 1.1.x HotSpot VM ?


Post a Comment:
  • HTML Syntax: NOT allowed



« February 2016