Mad about .NET A blog from Jose Fco Bonnin


"Types may declare locations that are associated with the type rather than any particular value of the type. Such locations are static fields of the type. As such, static fields declare a location that is shared by all values of the type. Just like non-static (instance) fields, a static field is typed and that type never changes. Static fields are always restricted to a single application domain basis, but they may also be allocated on a per-thread basis."

The paragraph above is the definition of static field extracted from the CLI specification. The text means that when we create a static field "f" inside a class "C", the value will not belong to any of the instances we create of C, instead its value is shared across all the instances and therefore "belongs" to the type C itself.

I've created a very simple class with one static and two instance fields, which you can see below.

   1: public class BusinessLogic
   2: {
   3:     public int instanceField1;
   4:     public int instanceField2;
   5:  
   6:     public static int staticField3 = 3;
   7:  
   8:     public BusinessLogic()
   9:     {
  10:         instanceField1 = 1;
  11:         instanceField2 = 2;
  12:     }
  13: }

I've run the code and I've created 5 instances of the class above, which we will check with WinDBG. To do it we can execute the next command:

!DumpHeap -type BusinessLogic

That will show something similar to the next:

Address               MT     Size
01dfa98c      006668c4      16    
01dfe898     006668c4       16    
01e027a4     006668c4       16    
01e0668c     006668c4       16    
01e13104     006668c4       16    
total 5 objects
Statistics:
      MT    Count    TotalSize   Class Name
006668c4        5           80        BusinessLogic
Total 5 objects

Once we have the address of the 5 instances we created we can dump the objects one by one by using the command !DumpObj [Address]. If we take the first one it will display something similar to:

Name: BusinessLogic
MethodTable: 001c68bc
EEClass: 00281abc
Size: 16(0x10) bytes
Fields:
          MT      Field   Offset   Type                VT   Attr         Value    Name
6f642b38  4000001        4      System.Int32     1    instance  1           instanceField1
6f642b38  4000002        8      System.Int32     1    instance  2           instanceField2
6f642b38  4000003       1c     System.Int32     1    static       3           staticField3

What we have done with this command is to examine the fields of one of the instances in memory of BusinessLogic. We can see that the object has the fields instanceField1, instanceField2 and staticField3 and its values are 1,2 and 3 respectively. So, all is as expected.

Lets focus now on the cool thing of static fields. We can see how "staticField3" is shared across al the instances we create of BusinessLogic by examing the EEClass of the objects. The 5 instances we created before have the same EEClass: "00281abc". If we examine it with the command !DumpClass 00281abc we will see that "staticField3" is present at EEClass level and its value is already initialized.

Class Name: BusinessLogic
mdToken: 02000002
Parent Class: 6f3d3ef0
Module: 001c64f0
Method Table: 001c68bc
Vtable Slots: 4
Total Method Slots: 6
Class Attributes: 100001 
NumInstanceFields: 2
NumStaticFields: 1
      MT          Field  Offset   Type                 VT    Attr         Value   Name
6f642b38    4000001        4      System.Int32   1     instance              instanceField1
6f642b38    4000002        8      System.Int32   1     instance              instanceField2
6f642b38  4000003      1c    System.Int32   1     static           3     staticField3

At this point we have demonstrated how the static fields and their values are shared across all the instances we create of a class.

In this sample we have used value types for the static field, but this also applies for reference types. This is very cool, because it allow us creating class designs where objects with a heavy load construction can be instantiated just once  i.e.

static object staticField;
....
if (staticField == null)
       staticField = new object();

This simple code will allow sharing the same instance of staticField across the entire application domain helping with the performance if staticField is hard to construct.

This does not mean that from now you must create all your "hard to construct" fields as static, because like always the gold hammer does not exist and static fields have a downside.

As we have seen the static field values are related to the EEClass, which are allocated on the loader heaps that are AppDomain specific, so this means they will be in memory until the AppDomain is unloaded.

Some time ago I read the .NET 3.5 Service Pack 1 would bring some nice improvements in the JIT compiler for the x86. Among them there were some modifications regarding how the JIT inlines methods (see my previous post about inlining).

Today I've seen this post from Vance Morrison where describes the heuristic used to determine when a candidate method must be inlined or not. Which according to him looks like follows:

"1. Estimate the size of the call site if the method were not inlined.

2. Estimate the size of the call site if it were inlined (this is an estimate based on the IL, we employ a simple state machine (Markov Model), created using lots of real data to form this estimator logic)

3. Compute a multiplier. By default it is 1

4. Increase the multiplier if the code is in a loop (the current heuristic bumps it to 5 in a loop)

5. Increase the multiplier if it looks like struct optimizations will kick in.

6. If InlineSize <= NonInlineSize * Multiplier do the inlining."

I invite you to read the entire post, I've found it very interesting.

I was commenting with friends some mistakes I found while reviewing the book Pro LINQ Object Relational Mapping with C# 2008. Despite the error's importance, it would be better that they do not appear in the book, moreover when the book must pass a technical review before be printed. i.e.

There is a paragraph that says “...one of the new features in .NET 3.0: the var keyword....” This is incorrect, the var keyword (in the context is used) does not appear in .NET 3.0, but in .NET 3.5 with the implicitly typed local variables and has a different syntax in other languages like VB. Therefore a more accurate affirmation could be “...one of the new features in C# 3.0: the var keyword....”.

Or “...the CLR is doing the heavy lifting for you by translating your queries into method calls...”. This is also incorrect since the Common Language Runtime (CLR) does not translate the LINQ queries into methods; instead each language compiler is in charge of that conversion, something that you can easily see by checking the IL and metadata generated by the compiler. This error is a bit more serious, because the reader can think it is better to use the method syntax instead of the LINQ syntax to avoid the translation performance cost during runtime, when it is not the case.

Anyway, the controversy came out when I said the author talks in the Entity Framework chapter about "Single-Table Mapping", regardless if the term is correct or not, the expression used in EF is a different one: Table-per-hierarchy. I think the author should have utilized the same term as in EF documentation. Names are very important to recognize the concepts behind them and the best is that within a context everybody uses the same, in this case the context was Entity Framework.

In my business area, credit card processing, we are sick to see how acquiring banks and payment processors use the same term for different things. i.e. Void, Reversal, Cancellation can be exactly the same operation or a totally different one depending on the company using the term, which can cause lot of confusion until you do not agree a nomenclature. Tables, views, methods, variables, classes ... none of them are an exception when you need to decide a good term. But IT world is not the only place where having the right name can help you to success, just remind the Oscar Wilde's play "The Importance of Being Earnest".  

Therefore, next time you need to select a name try to invest time enough deciding a good one that is descriptive enough, it would be better than having to waste it later on checking the documentation to remember what the term intended to mean.

ProLinq

I must confess that when I read the title of the book “Pro LINQ Object Relational Mapping with C# 2008” I had big pretensions about the book. ORM, as the author mentions in the introduction, is not a subject commonly treated for the .NET world and I was expecting a deep technical book. This has definitively conditioned my final opinion about it.

The book is divided in several parts. You can see below the main ones.

· First one provides you with a fast overview about the ORM concepts. It explains the problematic between database and conceptual models, problems addressed with ORM, laziness, persistence ignorance, etc.

· Second one presents LINQ to SQL and EF explaining the features each one provides.

· Third part does a “complete” implementation of a sample application which provides you some insights about what it does mean working with LINQ to SQL and EF.

The biggest worth of the book is probably the third part, where the author has not limited to write some excerpts of code, instead he has written some requirements and use cases to later on implement them as a developer would do in the “real world”, including even some unitary tests.

What I didn’t like is that, regardless it presents a wide range of concepts none of them is deeply treated, it always remains on the surface, which in my opinion has made of the book a “sugar free” version of what it could be.

Therefore if you are looking for a deep ORM, LINQ to SQL or EF this is not your book. Instead if you have heard noise about these technologies and you are searching for a text to help you with an overview of what is what and the possibilities they offer, Pro LINQ Object Relational Mapping with C# 2008 can be what you need.

One of the features we have in .NET is the ability to execute IL code generated dynamically, in fact there is a complete namespace to generate code at runtime called System.Reflection.Emit

Prior to .NET Framework 2.0 if we wanted to execute the IL code generated we needed to deal with a dynamic assembly making use of classes like the AssemblyBuilder, ModuleBuilder, etc. together with the IL code we can also emit symbolic information making possible to debug the dynamic code even within Visual Studio.

The main downside of this way of generating the IL code is (by design) that the generated code can not be garbage collected and therefore the memory is not released until the AppDomain is unload. This created some controversy about if this was a memory leak or not, which in any case is avoidable by loading everything in a separated AppDomain that can be unloaded when it's not used anymore.

With .NET Framework 2.0 we got the LCG (Lightweight Code Generation), which allows generating code at run time, without having to define the dynamic assembly nor type to contain the methods we create. In addition, the IL and the data structures related to the code generation are allocated on the managed, meaning that they can be garbage collected when there are no more references to the DynamicMethod class that is the main class of LCG.

Below you can see some simple code that dynamically emits the IL for a method "Talk" that concatenates two strings.

   1: class Demo
   2: {
   3:     public void RunDynamicCode()
   4:     {
   5:         MethodInfo concatMethodInfo = typeof(string).GetMethod("Concat", 
   6:             new Type[] { typeof(string), typeof(string) });
   7:  
   8:         DynamicMethod dm = new DynamicMethod("Talk", typeof(string), 
   9:             new Type[] { typeof(string) }, this.GetType(), true);
  10:  
  11:         ILGenerator generator = dm.GetILGenerator();
  12:         generator.Emit(OpCodes.Ldstr, "Hello ");
  13:         generator.Emit(OpCodes.Ldarg_0);
  14:         generator.EmitCall(OpCodes.Call, concatMethodInfo, null);
  15:         generator.Emit(OpCodes.Ret);
  16:  
  17:         Func<string,string> talkDelegate =
  18:             (Func<string, string>)dm.CreateDelegate(typeof(Func<string, string>));
  19:  
  20:         string result = talkDelegate("Jose Bonnin");
  21:  
  22:         Console.Write(result);
  23:         Console.ReadKey();
  24:     }
  25: }

Line 8 instantiates the DynamicMethod and specifies the name, the return type, an array with the parameters received and the type owner. The C# signature would be similar to "string Talk(string);"

Lines from 11 to 15 is where we write the IL code making use of the ILGenerator class. Note that in the line 16 we are emitting a call to the MethodInfo for the method String.Concat we obtained in the line 5.

Finally, in line 17 we do the coolest, we obtain a delegate for the method we have just generated that is callable from our C# code.

The main problem we experience with DynamicMethod is that we do not have the ability to generate debugging info for LCG, since the debugging API is based on metadata that the LCG does not have. In any case, not all is lost since we can continue debugging with WinDBG.

If we attach WinDBG to the code above we can effectively check that we have created a dynamic method and see the IL generated. To do it we just need to obtain a pointer to the DynamicMethod which can be obtained in different ways, an easy one for demo purposes is to the do a !DumpHeap -stat to obtain a list of the different objects grouped by type, then we just need to locate in the list the MT address of the type System.Reflection.Emit.DynamicMethod and run the command !DumpHeap -mt [address] over it. Which will show something similar to this:

0:003> !DumpHeap -mt 6fbf026c
Address      MT         Size
01d0e028   6fbf026c    56
total 1 objects
Statistics:
MT         Count   TotalSize    Class Name
6fbf041c        1            56     System.Reflection.Emit.DynamicMethod
Total 1 objects

Now that we have obtained the address (01d0e028) we can run the command DumpIL to see the dynamic IL generated.

0:003> !DumpIL 01d0e028
This is dynamic IL. Exception info is not reported at this time.
If a token is unresolved, run "!do " on the addr given
in parenthesis. You can also look at the token table yourself, by
running "!DumpArray 01d0e62c".

IL_0000: ldstr 70000002 "Hello "
IL_0005: ldarg.0
IL_0006: call a000003 (01d0e560)
IL_000b: ret

In this post we have seen how we do not need to look to "new" technologies like WPF, Silverlight or WCF to find cool things within .NET