March 2006 - Posts

In my post about generics a couple of days ago (see http://community.bartdesmet.net/blogs/bart/archive/2006/03/22/3831.aspx, updated the demo code because of a problem with the performance measurement :O) I've been using the oldfashioned way to do performance measurement in .NET using P/Invoke to the Win32 API. Basically you need to do the following:

  1. Import the following native functions (using System.Runtime.InteropServices;):

       [DllImport("kernel32.dll")]
       internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

       [DllImport("kernel32.dll")]
       internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);
  2. Add the following member to the class:

       static decimal GetSecondsElapsed(long start, long stop)
       {
          long queryFrequency;
          QueryPerformanceFrequency(out queryFrequency);
          decimal result = Convert.ToDecimal(stop - start) / Convert.ToDecimal(queryFrequency);
          return Math.Round(result, 6);
       }

  3. Perform testing as follows:

          long begin;
          QueryPerformanceCounter(out begin);

          // code to test for performance


          long end;
          QueryPerformanceCounter(out end);
          decimal seconds = GetSecondsElapsed(begin, end);

This might look a bit overcomplicated and it actually is, so the .NET Framework guys created a new helper class to assist in this kind of work: System.Diagnostics.Stopwatch was born. Here is how to use it:

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;

class Gen
{
   [DllImport("kernel32.dll")]
   internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

   [DllImport("kernel32.dll")]
   internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);

   public static void Main()
   {
      TimeSpan good = DoGood();
      TimeSpan bad = DoBad();
      decimal ugly = DoUgly();

      Console.WriteLine("The good: " + good);
      Console.WriteLine("The bad:  " + bad);
      Console.WriteLine("The ugly: " + ugly);
   }

   static TimeSpan DoGood()
   {
      Stopwatch stopwatch = new Stopwatch();
      stopwatch.Start();

      Do();

      stopwatch.Stop();
      return stopwatch.Elapsed;
   }

   static TimeSpan DoBad()
   {
      DateTime begin = DateTime.Now;

      Do();

      DateTime end = DateTime.Now;
      return end - begin;
   }

   static decimal DoUgly()
   {
      long begin;
      QueryPerformanceCounter(out begin);

      Do();

      long end;
      QueryPerformanceCounter(out end);

      return GetSecondsElapsed(begin, end);
   }

   static void Do()
   {
      List<int> lst = new List<int>();

      for (int i = 0; i < 1000000; i++)
         lst.Add((i % 2 == 0 ? 1 : -1));

      int sum = 0;
      foreach (int i in lst)
         sum += i;
   }

   static decimal GetSecondsElapsed(long start, long stop)
   {
      long queryFrequency;
      QueryPerformanceFrequency(out queryFrequency);
      decimal result = Convert.ToDecimal(stop - start) / Convert.ToDecimal(queryFrequency);
      return Math.Round(result, 6);
   }
}

The output is the following:

>gen
The good: 00:00:00.0405179
The bad:  00:00:00.0500720
The ugly: 0.042730

The key takeaway of all this stuff is that DateTime.Now hasn't the best timer resolution to perform exact performance measurement. Rather you should use the Stopwatch class (introduced in .NET 2.0) which encapsulated the low-level platform stuff to perform an exact measurement. So the pattern looks like this:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

// code to be tested

stopwatch.Stop();
return stopwatch.Elapsed; //alternative properties include ElapsedMilliseconds and ElapsedTicks

A last alternative is the following (cute) piece of code:

class PerformanceTester : IDisposable
{
   private Stopwatch stopwatch;
   private TextWriter output;

   public PerformanceTester(TextWriter output)
   {
      this.output = output;
      stopwatch = new Stopwatch();
      stopwatch.Start();
   }

   public void Dispose()
   {
      stopwatch.Stop();
      output.WriteLine(stopwatch.Elapsed);
   }
}

With this, you can do the following:

static void DoCute()
{
   using (new PerformanceTester(Console.Out))
   {
      Do();
   }
}

Isn't this cute :$

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Only for CLR hardcore freaks, the SSCLI version 2.0 has been released to the web. SSCLI (codenamed Rotor) stands for Shared Source Common Language Infrastructure and is Microsoft's shared source implementation of the CLI (ECMA 335) and the C# compiler (ECMA 334). So, it contains the source of an entire working CLR implementation, a C# compiler and much more such as ilasm, ildasm, cordbg, nmake, build, etc. I'll blog about adventures in the SSCLI soon as I have quite some posts in RC stage in my offline to-be-blogged queue (which happens to fill faster than it's being emptied).

Anyway, download the SSCLI 2.0 over here: http://www.microsoft.com/downloads/details.aspx?FamilyId=8C09FD61-3F26-4555-AE17-3121B4F51D4D&displaylang=en. Notice this build only runs on Windows XP SP2 (although you can investigate the source files on other platforms as well). Check out the link to the 1.0 release as well for an older build (2002!) that runs on other platforms too.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Readers familiar with my blog know I'm an IL addict to find out how things work. The IL code of an assembly contains all of the information you need to know how an application works internally or how the CLR and language compilers manage certain constructs. However, some people are worried about the power of this ildasm.exe thing because it reveals quite a lot of the application. Now, thanks to Mr. Von Neumann, data and instructions are treated in similarly, residing in the same memory space and in the end every application - managed or not - consists of instructions sent to the processor. So, in the end, every application can be reverse engineered (there exist tools to "decompile" .NET applications to a higher-level .NET language such as C#) but the more low level the code is, the more difficult it is to understand what's going on at the higher level. That's where the real problem with IL (the same holds for Java bytecode by the way) comes into play: it keeps applications rather readable. How to protect yourself against all of this?

  • Obfuscate your assemblies using Dotfuscator (from PreEmptive Solutions) which you can download from www.preemptive.com/products/dotfuscator/index.html. The free community edition ships with Visual Studio 2005. Basically, the idea of obfuscation is rather straightforward: by applying a series of transformations on the IL code, a functionally equivalent of the original application is created, but much less readable and understandable. A bunch of transforms are available (some of those only in the Pro edition of the tool) such as renaming of types and members, encryption of strings, control flow obfuscation, "overload-induction", pruning (also boosts performance), assembly merging, watermarking (see further too for info on signing of assemblies), etc. A tool called Lucidator makes obfuscated assemblies still debuggable. As of .NET Framework 2.0, the System.Reflection namespace contains two attributes that help to drive the obfuscation through metadata that can be consulted by the Dotfuscator tool, being:
    • ObfuscateAssemblyAttribute to drive the obfuscation of an assembly. It allows to specify whether the assembly is public or private (as internal part of an application) and whether the obfuscation attribute has to be stripped after obfuscation (to make obfuscation more or less undetectable).
    • ObfuscationAttribute is used to instruct tools how to apply obfuscation to an assembly, a type or a member. Using this, you can disable obfuscation for certain members of classes of your choice and you can pass a string message to the obfuscation tool (dependent from the target obfuscation tool).
  • Protect all your assemblies from tampering by signing the assembly with a strong name. This is available in Visual Studio 2005 through the IDE (project properties) but you can do the same using the assembly-attribute AssemblyKeyFileAttribute:
       [assembly: AssemblyKeyFile("..\\..\\key.snk")]
    where ..\\..\\key.snk points to the file key.snk in the project folder using a relative path starting from the bin\Debug or bin\Release folder. Also consult my Strong named assemblies and the GAC inside out post for more information about this.
  • Suppress disassembly to IL using the ildasm.exe tool by applying the SuppressIldasmAttribute from the System.Runtime.CompilerServices namespace:
       [assembly: SuppressIldasm()]
    in AssemblyInfo.cs (similar for Visual Basic). When you try to disassembly the code now, you end up with the following warning:
       >ildasm DemoStuff.exe /out:demostuff.il
       Protected module -- cannot disassemble
    Notice this does not protect an assembly against things such as reflection and is *not* an obfuscator.
    (If you've been busy with .NET since day one, you might recall that in the early betas (somewhere in 2001) the ilasm.exe tool (not ilDasm.exe!) had a /owner switch that could be used to "copyright" an assembly and protect it against disassembly.)

Have fun!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Discussions of the power of generics a pretty common in some groups. So in order to support my arguments in those discussions, I created a little quick-and-dirty demo of generics in Java and in C#/CLR concerning the boxing/unboxing issues. You probably know that boxing/unboxing of value types causes a serious performance hit. Needless to say that you just want generics to take this problem away, by using something like List<int> as kind of an improved version of int[] (but with variable length etc). Beside of that you also get type-safety and type-checking all the time, something you don't have when using a plain old ArrayList in .NET stuffed with int's all over the place.

 

Non-generic collections

The first difference between C# and Java is the way you can add value types to a non-generic collection. In Java you have to wrap those in a so-called wrapper class (e.g. Integer), whileas .NET has boxing/unboxing on the IL level directly (using box and unbox statements):

//new ArrayList().Add(1);
newobj instance void [mscorlib]System.Collections.ArrayList::.ctor() //instantiate ArrayList
ldc.i4.1 //load 1
box [mscorlib]System.Int32 //box it
callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) //put the object (= wrapper for integer 1) in the list

In Java you'd end up with some bytecode like this (I just took the dump of javap.exe -c because of my lack of manual bytecode generation maturity :-)):

//new ArrayList().add(new Integer(1));
class Box extends java.lang.Object{
Box();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   new     #2; //class java/util/ArrayList
   3:   dup
   4:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   7:   new     #4; //class java/lang/Integer
   10:  dup
   11:  iconst_1
   12:  invokespecial   #5; //Method java/lang/Integer."<init>":(I)V
   15:  invokevirtual   #6; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
   18:  pop
   19:  return
}

Notice I'm using J2SE 1.5 where ArrayList now is a generic collection which means versioning hell :-). Actually the compiler tells me for every use of a non-generic collection I'm writing unsafe code which is not my mistake but the (old) framework's:

Note: box.java uses unchecked or unsafe operations
Note: Recompile with -Xlint:unchecked for details.

<Intermezzo Title="The Java versioning hell">

I always like to stress .NET was built from ground up to support versioning of applications and portability of "old code" to a newer runtime without modifications thanks to various runtime constructs (side-by-side CLR versions; versioned assemblies; publisher policies and version redirects; etc) but also thanks to the well-thought design of e.g. C#, such as:

  • The lack of checked exceptions: in Java you can declare methods with a throws clause indicating the exceptions the method can throw and therefore which you should catch too. However, such a throws list can be incomplete over the course of time, especially when you are implementing an interface and your specific implementation can throw additional types of exceptions. Either you'd have to create a bunch of Exception subclasses to act as wrappers and deploy those alongside with the interface you've defined or you just fight the checked exception mechanism as a lazy developer by swallowing exceptions all the time using a catch-all block or by declaring every method of yours as throws Exception to get rid of the nasty compiler warnings.
  • Making methods not virtual by default, leading to a performance increase but also aiding in fighting against versioning troubles (assume you create a class B deriving from class A and add a method C to B - which will be virtual by default; then assume the new version of A also has a method called C with a similar signature, whoops - code broken) by requiring stuff such as virtual methods and overrides to be explicit.

I'm sure other examples exist, but let's keep it a short and clean. Not to talk about the "deprecated methods mantra" (although that happens to be an illness of most frameworks today).

</Intermezzo>

Back to our generics investigation in Java. Notice the generated code is actually creating an ArrayList instance without initial knowledge of the type it's going to "host". Later on generic things are done like this:

   15:  invokevirtual   #6; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z

meaning an object of type java.lang.Object is added to the collection (in this case an instance of Integer, see lines 11-12). In essence, the list doesn't have runtime knowledge of the target type which is the definition of a non-generic list (so, in Java the new generic ArrayList implements non-generic functionality too - as a form of backward compatibility - by setting the target type to the mother of all objects, java.lang.Object).

 

Generic collections

On to generic collections now. Assume the following piece of code in C#:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

class Gen
{
   [DllImport("kernel32.dll")]
   internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

   [DllImport("kernel32.dll")]
   internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);

   public static void Main()
   {
      long begin;
      QueryPerformanceCounter(out begin);

      List<int> lst = new List<int>();

      for (int i = 0; i < 1000000; i++)
         lst.Add((i % 2 == 0 ? 1 : -1));

      int sum = 0;
      foreach (int i in lst)
         sum += i;

      long end;
      QueryPerformanceCounter(out end);

      Console.WriteLine(GetSecondsElapsed(begin, end)); //UPDATED 03/24/06 - forgot GetSecondsElapsed call
   }

   static decimal GetSecondsElapsed(long start, long stop)
   {
      long queryFrequency;
      QueryPerformanceFrequency(out queryFrequency);
      decimal result = Convert.ToDecimal(stop - start) / Convert.ToDecimal(queryFrequency);
      return Math.Round(result, 6);
   }
}

The core code is indicated in bold. First of all, notice the generic collections are living in System.Collections.Generic, not fighting with the non-generic brothers and sisters in System.Collections, actually leading to 100% backward compatibility without nasty compiler warnings telling how bad the framework was in the past because of the lack of generics and how you - as an innocent developer - have to be blamed of having written such code ever :P (talking the Java-way). Don't bother about the perf counting stuff in order to get an accurate timing result.

The real fun is over here:

      List<int> lst = new List<int>();

      for (int i = 0; i < 1000000; i++)
         lst.Add((i % 2 == 0 ? 1 : -1));

      int sum = 0;
      foreach (int i in lst)
         sum += i;

First of all, we create a generic list containing int's. Notice no wrappers are needed. Further on, the list is filled with stuff that's retrieved again and used in a sum (avoiding overflow by taking only 1 and -1 values). In IL this results in:

  IL_0009:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() // List<int> lst = new List<int>();
  IL_000e:  stloc.1            // List<int> lst = new List<int>();
  IL_000f:  ldc.i4.0           // for (int i = 0; i < 1000000; i++)
  IL_0010:  stloc.2            // for (int i = 0; i < 1000000; i++)
  IL_0011:  br.s       IL_0027 // jump to begin of loop
  IL_0013:  ldloc.1            // keep lst object reference on the stack needed for instruction IL_001d
  IL_0014:  ldloc.2            // i % 2 == 0 ? 1 : -1
  IL_0015:  ldc.i4.2           // i % 2 == 0 ? 1 : -1
  IL_0016:  rem                // i % 2 == 0 ? 1 : -1
  IL_0017:  brfalse.s  IL_001c // i % 2 == 0 ? 1 : -1
  IL_0019:  ldc.i4.m1          // i % 2 == 0 ? 1 : -1
  IL_001a:  br.s       IL_001d // short branch
  IL_001c:  ldc.i4.1           // i % 2 == 0 ? 1 : -1
  IL_001d:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0) // lst.Add(...);
  IL_0022:  nop                // debugger breakpoint helper instruction
  IL_0023:  ldloc.2            // for (int i = 0; i < 1000000; i++) ~ for (int i = 0; i < 1000000; i = i + 1)
  IL_0024:  ldc.i4.1           // for (int i = 0; i < 1000000; i++) ~ for (int i = 0; i < 1000000; i = i + 1)
  IL_0025:  add                // for (int i = 0; i < 1000000; i++) ~ for (int i = 0; i < 1000000; i = i + 1)
  IL_0026:  stloc.2            // for (int i = 0; i < 1000000; i++) ~ for (int i = 0; i < 1000000; i = i + 1)
  IL_0027:  ldloc.2            // for (int i = 0; i < 1000000; i++)
  IL_0028:  ldc.i4     0xf4240 // for (int i = 0; i < 1000000; i++)
  IL_002d:  clt                // for (int i = 0; i < 1000000; i++)
  IL_002f:  stloc.s    V_5     // for (int i = 0; i < 1000000; i++) // temporary boolean
  IL_0031:  ldloc.s    V_5     // for (int i = 0; i < 1000000; i++) // temporary boolean
  IL_0033:  brtrue.s   IL_0013 // jump to loop body
  IL_0035:  ldc.i4.0           // int sum = 0;
  IL_0036:  stloc.3            // int sum = 0;
  IL_0037:  nop                // debugger breakpoint helper instruction
  IL_0038:  ldloc.1    // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
  IL_0039:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
                       // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
  IL_003e:  stloc.s    V_6
                       // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
  .try
  {
    IL_0040:  br.s       IL_004e // begin iterator loop
    IL_0042:  ldloca.s   V_6
                         // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
    IL_0044:  call       instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
                         // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
    IL_0049:  stloc.2    // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
    IL_004a:  ldloc.3    // sum += i; ~ sum = sum + i;
    IL_004b:  ldloc.2    // sum += i; ~ sum = sum + i;
    IL_004c:  add        // sum += i; ~ sum = sum + i;
    IL_004d:  stloc.3    // sum += i; ~ sum = sum + i;
    IL_004e:  ldloca.s   V_6
                         // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
    IL_0050:  call       instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
                         // foreach (int i in lst) ~ int i = 0; for (List<int>.Enumerator e = lst.GetEnumerator(); e.MoveNext(); i = e.Current)
    IL_0055:  stloc.s    V_5 // temporary boolean
    IL_0057:  ldloc.s    V_5 // temporary boolean
    IL_0059:  brtrue.s   IL_0042 // iterator loop - jump to begin
    IL_005b:  leave.s    IL_006c // leave try block
  }  // end .try
  finally
  {
    IL_005d:  ldloca.s   V_6 // stuff to support Enumerator : IDisposable
    IL_005f:  constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
    IL_0065:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_006a:  nop        // debugger breakpoint helper instruction
    IL_006b:  endfinally // end of SEH block
  }  // end handler
  IL_006c:  nop // debugger breakpoint helper instruction

The result of the execution is 41 ms.

On to the equivalent in Java:

import java.util.*;

class Gen
{
   public static void main(String[] args)
   {
      long begin = System.currentTimeMillis();

      //List<int> lst; //won't compile
      List<Integer> lst = new ArrayList<Integer>();

      for (int i = 0; i < 1000000; i++)
         lst.add((i % 2 == 0 ? 1 : -1));

      int sum = 0;
      for (int i = 0; i < lst.size(); i++)
         sum += lst.get(i);

      long end = System.currentTimeMillis();
      System.out.println(end - begin);
   }
}

Notice you need to use the wrapper class again to instantiate the generic collection, although the add(...) method is intelligent enough to do wrapping itself. Needless to say the lack of enumerator language support leads to less elegant code :P. Investigate the .class file using the javap.exe tool which comes with the J2SE SDK:

class Gen extends java.lang.Object{
Gen();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   lstore_1
   4:   new     #3; //class java/util/ArrayList
   7:   dup
   8:   invokespecial   #4; //Method java/util/ArrayList."<init>":()V
   11:  astore_3
   12:  iconst_0
   13:  istore  4
   15:  iload   4
   17:  ldc     #5; //int 1000000
   19:  if_icmpge       50
   22:  aload_3
   23:  iload   4
   25:  iconst_2
   26:  irem
   27:  ifne    34
   30:  iconst_1
   31:  goto    35
   34:  iconst_m1
   35:  invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   38:  invokeinterface #7,  2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
   43:  pop
   44:  iinc    4, 1
   47:  goto    15

   50:  iconst_0
   51:  istore  4
   53:  iconst_0
   54:  istore  5
   56:  iload   5
   58:  aload_3
   59:  invokeinterface #8,  1; //InterfaceMethod java/util/List.size:()I
   64:  if_icmpge       92
   67:  iload   4
   69:  aload_3
   70:  iload   5
   72:  invokeinterface #9,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
   77:  checkcast       #10; //class java/lang/Integer
   80:  invokevirtual   #11; //Method java/lang/Integer.intValue:()I
   83:  iadd
   84:  istore  4
   86:  iinc    5, 1
   89:  goto    56

   92:  invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   95:  lstore  5
   97:  getstatic       #12; //Field java/lang/System.out:Ljava/io/PrintStream;
   100: lload   5
   102: lload_1
   103: lsub
   104: invokevirtual   #13; //Method java/io/PrintStream.println:(J)V
   107: return
}

Both blocks have been indicated in colors. Notice the boxing stuff:

   35:  invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

and the unboxing stuff:

   72:  invokeinterface #9,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
   77:  checkcast       #10; //class java/lang/Integer
   80:  invokevirtual   #11; //Method java/lang/Integer.intValue:()I

which is introduced automatically. And finally as you can see the generic parameter is just java.lang.Object:

   38:  invokeinterface #7,  2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

   72:  invokeinterface #9,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;

Execution times tell very much about this approach: 301 ms, a factor 7.3 (worse) compared to the CLR-equivalent. (UPDATED 03/24/06 - Modified the orginal - wrong - result based on the GetSecondsElapsed code.)

 

Conclusion

Generics in .NET are not an artificial construct like in Java and really lead to the generation of new types at runtime (or at ngen-time to be complete) significantly increasing performance especially when working with value types that don't require boxing/unboxing anymore. Using this basic test you come to the conclusion that .NET is 7.3 times faster than Java. Stay tuned for more stuff on generics somewhere in the near future.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

I just ran across this issue. Take a look at the following piece of code:

using System;
using System.Runtime.InteropServices;

namespace Bla
{
    using net.bartdesmet.www;

    class Program
    {

        [DllImport("kernel32.dll")]
        internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

        [DllImport("kernel32.dll")]
        internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);

        static void Main(string[] args)
        {
            HelloWorld svc = new HelloWorld();
            svc.Send(new byte[] {123}); /* Runs fine */
            TestSend(svc);
        }
       
        private static decimal TestSend(HelloWorld svc)
        {
            long start, stop;
            QueryPerformanceCounter(out start);

            svc.Send(new byte[] {123}); /* MissingMethodException in debugger */
           
            QueryPerformanceCounter(out stop);

            return GetSecondsElapsed(start, stop);
        }
    }
}

HelloWorld is actually a proxy class generated for an online web service. It will just rune fine on a desktop (or portable) machine. However, on a Smartphone it fails to run with a MissingMethodException while the debugger points to the svc.Send(new byte[] {123}); line of code. So, what' your first reaction? Regenerating the proxy, moving the call outside the TestSend method and ow, it works fine. Starting to think much too far about parameter passing stuff etc, smashing your head on the table. Every developer knows the pain :-).

Finally I tried to comment out the QueryPerformanceCounter stuff and there it goes, all problems vanish. So what's the problem. Actually it's not the indicated svc.Send(...) line but the line just on top of it that's causing the troubles. Basically, MissingMethodException is one of the exceptions originating from the runtime itself (the CLR). So you can't really rely on the debugger's marker when the exception is thrown (you won't find a stacktrace either). The solution to this problem looks as follows (on Smartphone):

        [DllImport("CoreDll.dll")]
        internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

        [DllImport("CoreDll.dll")]
        internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);

Which makes sense if you're familiar with Windows CE programming (coredll.lib and co). Again a problem that could be avoided by being more careful when using the magic of CTRL-C, CTRL-V in Visual Studio :-). As the matter in fact, the problem was slightly more hidden because of my love for regions in C#:

#region P/Invoke stuff
[DllImport("kernel32.dll")]
internal static extern int QueryPerformanceCounter(out Int64 lpPerformanceCount);

[DllImport("kernel32.dll")]
internal static extern int QueryPerformanceFrequency(out Int64 lpPerformanceCount);

#endregion

Or how to do "bug hiding" :D.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

For those of you who don't have an MSDN Subscription and want to jump on the train of public betas of various new technologies and products, check out this site: http://www.microsoft.com/technet/prodtechnol/beta/preregister.mspx.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Finally, the VS2005 release is complete with the availability of the Team Foundation Server (more info on http://msdn.microsoft.com/vstudio/products/vsts/tfs/default.aspx). It's great to see the VS2005 TFS software available on MSDN Subscriptions (TFS Workgroup Edition) and I'll start downloading it asap. I'm currently running a project on TFS Beta 3 Refresh (hadn't the time to move to the RC because of time constraints on the configuration management of the project) and I enjoyed the beta pretty much. So I'm sure I'll have even more fun working with the RTM bits (and hopefully the setup goes smoother than in the beta 3 stage, which was a rather painful experience although I RTMF'ed pretty well :D). Anyway, have fun with 448 MB of pure VS Team fun!Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Read all about it over here: http://msdn.microsoft.com/vstudio/teamsystem/team/tfs_released/. MSDN Subscribers will see the bits appearing on the MSDN Subscriber Downloads website on Monday March 20th. What a stressy weekend it will be with sleepless nights waiting for the TFS bits to be sucked to my machine :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Last Monday the MMC 3.0 software was released to the web. You can find it over here.

In my opinion this is a great release. Worth to know, originally this MMC release was going to be version 2.1 but due to the great set of enhancements made to the technology including managed code support, it was promoted to a major release, resulting in 3.0. Existing .msc files will be upgraded to 3.0 when you close the according MMC window (btw, did you know .msc files are XML-based?). I haven't seen the MMC 3.0 SDK (for managed code) yet as a download (Platform SDK stuff that is), but you can already find the documentation online at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/managedmmc/html/28aa1a22-e250-45da-b162-8c0b11338caf.asp. Once the API has been released publicly, I'll post about the development proces of MMC snap-ins using managed code (which was not really possible in the past without drowning in plumbing P/Invoke code).

Cheers!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Introduction

Although I'm primarily a C# guy, often I have to look at other languages in the .NET universe as well. Actually I come from a big Visual Basic background in the past (in the pre-.NET era which started for me in early 2001) having written several applications in Visual Basic. Currently I'm working on the Visual Basic 2005 Coach for MSDN Belux (more info will follow later) and concentrating on VB again. I'm pretty happy to see a bunch of new features in VB2005 which a ton of developers will benefit from in their daily lives, including stuff like generics, nullable types, operator overloading, partial types, my favorite using-statement (cf. IDisposable pattern), unsigned types (such as UInteger), the Continue statement for usage in loops, XML documentation support, etc. Also the rediscovery of edit and continue is certainly a big plus in VB2005 compared to VB.NET 2002/2003.

The "My" Thing

However, one of the things that deserves a bit of additional explanation is the My namespace in VB2005 to get easier access to several "things". Let's take a look. The idea if fairly straightforward: using the My namespace you can gain easy access to a wide variety of interesting objects and stuff on the system, related to the computer, the application, the user, etc. It's rather useless to start looking at all of the stuff accessible through the My namespace because the key goal is just to provide an easy way to "unlock the potential" of the framework through an approachable namespace that fits it all. So, the best recommendation I can do is to take a look at the namespace yourself in the Visual Studio 2005 environment with IntelliSense.

Just to name one example... I can't recall the number of times I've been looking for code to determine the current screen resolution in C#. Although it's a pretty simple piece of code I don't seem to remember the exact way to do it. Using the My namespace it's as easy as My.Computer.Screen.WorkingArea. Nice isn't it?

Diving deeper

Now, how does this work? Just create a simple Windows Forms project in Visual Basic 2005 and compile it. Then go to the Visual Studio 2005 Command Line and take a look at the .exe file's IL-code using ildasm.exe. The output will look somewhat like this:

 

Basically, the application's entrypoint lives in the My.MyApplication object (the Main sub). As you can see, the MyApplication object is an extension of some base class in the Microsoft.VisualBasic namespace:

.class private auto ansi beforefieldinit OhMy.My.MyApplication
extends [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
.custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 01 00 00 00 00 00 )
.custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string,
                                                                                    string) = ( 01 00 0A 4D 79 54 65 6D 70 6C 61 74 65 07 38 2E // ...MyTemplate.8.
                                                                                                30 2E 30 2E 30 00 00 )                          // 0.0.0..
} // end of class OhMy.My.MyApplication

One particular point of interest in here is the fact that the object is annotated with a GeneratedCodeAttribute which indicates this code is being generated by a tool, in this case the Visual Basic compiler. The same approach is taken for things such as MyComputer, which is also inheriting from some base class that's defined in the Microsoft.VisualBasic namespace. Just take a look at the different defined namespaces to get more info about the different. For example, the syntax My.Computer will be translated to OhMy.My.MyProject.Computer (with OhMy the namespace for my project). In IL the equivalent is of course OhMy.My.MyProject.get_Computer which returns an instance of type OhMy.My.MyComputer. This property getter is responsible to get an instance of the Microsoft.VisualBasic.Devices.Computer object:

.method assembly specialname static class OhMy.My.MyComputer
        get_Computer() cil managed
{
  .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       16 (0x10)
  .maxstack  1
  .locals init ([0] class OhMy.My.MyComputer Computer)
  IL_0000:  nop
  IL_0001:  ldsfld     class OhMy.My.MyProject/ThreadSafeObjectProvider`1<class OhMy.My.MyComputer> OhMy.My.MyProject::m_ComputerObjectProvider
  IL_0006:  callvirt   instance !0 class OhMy.My.MyProject/ThreadSafeObjectProvider`1<class OhMy.My.MyComputer>::get_GetInstance()
  IL_000b:  stloc.0
  IL_000c:  br.s       IL_000e
  IL_000e:  ldloc.0
  IL_000f:  ret
} // end of method MyProject::get_Computer

This is implementing a thread-safe singleton-like pattern to retrieve the Computer object using a generic class ThreadSafeObjectProvider that instantiates the given type using the default constructor:

.method assembly specialname instance !T
        get_GetInstance() cil managed
{
  .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       38 (0x26)
  .maxstack  2
  .locals init ([0] !T GetInstance,
           [1] bool VB$CG$t_bool$S0)
  IL_0000:  nop
  IL_0001:  ldsfld     !0 class OhMy.My.MyProject/ThreadSafeObjectProvider`1<!T>::m_ThreadStaticValue
  IL_0006:  box        !T
  IL_000b:  ldnull
  IL_000c:  ceq
  IL_000e:  stloc.1
  IL_000f:  ldloc.1
  IL_0010:  brfalse.s  IL_001c
  IL_0012:  call       !!0 [mscorlib]System.Activator::CreateInstance<!T>()
  IL_0017:  stsfld     !0 class OhMy.My.MyProject/ThreadSafeObjectProvider`1<!T>::m_ThreadStaticValue
  IL_001c:  ldsfld     !0 class OhMy.My.MyProject/ThreadSafeObjectProvider`1<!T>::m_ThreadStaticValue
  IL_0021:  stloc.0
  IL_0022:  br.s       IL_0024
  IL_0024:  ldloc.0
  IL_0025:  ret
} // end of method ThreadSafeObjectProvider`1::get_GetInstance

This piece of code checks whether the field m_ThreadStaticValue (with the generic type) is not null. If so, it's just returned (path IL_0010 --> IL_001c), otherwise the object is instantiated using an Activator (that finally calls the default constructor) and stored in the field m_ThreadStaticValue:

.field private static !T m_ThreadStaticValue
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.ThreadStaticAttribute::.ctor() = ( 01 00 00 00 )

<Remark>Notice that the .NET Framework code guidelines inside the VB implementation itself (looking at the IL) are somewhat violated! One has defined a property GetInstance in the generic ThreadSafeObjectProvider, which should really be a methodin my opinion. Properties have to be lightweight whileas the getter of the GetInstance property over here will even invoke the Activator (one time). Beside of that, a property starting with Get looks a bit weird.</Remark>

Now, going a little further, how does the compiler get the instructions to insert this piece of code? Basically, it will always do this regardless of the build environment or the tools you're using. For example, a simple application like

Module Test
   Sub Main
   End Sub
End Module

compiled through vbc.exe will emit a My namespace automatically (check!). However, the "MyApplicationCodeGenerator" which you can find in the .vbproj file of your project, also guides the exact compilation process. Let's take a look:

  <ItemGroup>
    <None Include="My Project\Application.myapp">
      <Generator>MyApplicationCodeGenerator</Generator>
      <LastGenOutput>Application.Designer.vb</LastGenOutput>
    </None>
    <None Include="My Project\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <CustomToolNamespace>My</CustomToolNamespace>
      <LastGenOutput>Settings.Designer.vb</LastGenOutput>
    </None>
  </ItemGroup>

As you can see, the .myapp file of the project is included in the build process somewhere. What's in this file?

<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MySubMain>true</MySubMain>
  <MainForm>Form1</MainForm>
  <SingleInstance>false</SingleInstance>
  <ShutdownMode>0</ShutdownMode>
  <EnableVisualStyles>true</EnableVisualStyles>
  <AuthenticationMode>0</AuthenticationMode>
  <ApplicationType>0</ApplicationType>
  <SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

This piece of XML is mapped on a bunch of settings you can set on the project's properties in Visual Studio. One example is the MySubMain setting, which indicates that the Main entrypoint of the application is generated automatically in the OhMy.My.MyApplication class.

What about C#?

Some of you will wonder whether it's possible to use this flexibility in C# too. The short answer is: "not directly". In order to get it working, add a reference to Microsoft.VisualBasic.dll and import the namespace Microsoft.VisualBasic.Devices as follows:

using My = Microsoft.VisualBasic.Devices;

Once you've done so, you can use (some of) the functionality of the VB My namespace in C# as well, e.g.:

new My.Computer().Screen.WorkingArea;

Notice you have to instantiate the object in C# because we hook in to the My namespace using a different approach, i.e. no stubs with accessors for "Computer" have been created as this was the case in VB with the MyComputer generated class inheriting from the Microsoft.VisualBasic.Devices.Computer using a singleton pattern behind the scenes. Of course you could create some stubs yourself which are easy to recycle whenever you need them (e.g. by changing the MSBuild files to insert that piece of logic into every application). To mimic this behavior completely, you could insert the following class to your root app namespace in C#:

class My
{
    private static Computer computer;

    public static Computer Computer
    {
        get
        {
            if (computer == null)
                computer = Activator.CreateInstance<Computer>();
            return computer;
        }
    }
}

A more generic way of doing this looks as follows (including some basic sample code of using it in a form):

using System;
using System.Drawing;
using Microsoft.VisualBasic.Devices;

namespace OhMy
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Rectangle r = My.Computer.Screen.WorkingArea;
        }
    }

    internal class ThreadSafeObjectProvider<T>
    {
        private T theInstance;

        public T GetInstance()
        {
            if (theInstance == null)
                theInstance = Activator.CreateInstance<T>();
            return theInstance;
        }
    }

    internal class My
    {
        private static ThreadSafeObjectProvider<Computer> computerObjectProvider;

        static My()
        {
            computerObjectProvider = new ThreadSafeObjectProvider<Computer>();
        }

        public static Computer Computer
        {
            get
            {
                return computerObjectProvider.GetInstance();
            }
        }
    }
}

Also notice we're creating a class over here, instead of a namespace. In Visual Basic, My is really a namespace but the easy access to things such as Computer is done through the use of a new attribute, called Microsoft.VisualBasic.HideModuleNameAttribute. This pattern in VB (which can be used to extend the My namespace easily) looks like this:

Namespace My
    <HideModuleName()> _
    Module CustomMyThing
        Private ReadOnly thingie As MyThing = New MyThing

        Public ReadOnly Property Thing() As MyThing
            Get
                Return thingie
            End Get
        End Property
    End Module
End Namespace

Class MyThing
    ' Stuff goes here
End Class

Basically, the shortcut My.Thing will work only because the Visual Basic tools support this shorthand convenient syntax when applying the attribute.

A Visual Studio Template for C#

Let's bring the My stuff to C# in a convenient way! To do so, I created a .vsi package that contains an item template to include the needed My stuff to a Visual Studio 2005 C# project with support for My.Computer (other stuff has not been implemented yet, will take a look at it if I have some spare free time left). If you don't know how the creation of a Visual Studio template looks like, keep an eye on my blog. I'll try to post some notes about it over here pretty soon. In essence you have to create a .vsi file which is really a .zip file containing another zip with the template files and some XML files describing what's in the template and how it should be displayed in VS2005.

To install the template, do the following:

  1. Download the My CSharp template over here.
  2. Rename the file to MyCSharp.vsi (stripping off the .zip portion)
  3. Double-click the file in Windows Explorer. This will bring up the VS Content Installer to install the template.

  4. Click Next, confirm to install the content by clicking Yes on the "No Signature Found" dialog (if you trust me :-)) and finally click Finish.

  5. Open Visual Studio 2005, create a Visual C# project (e.g. Windows Forms).
  6. Go to Solution Explorer, click the project node and choose Add Item. The My namespace supporting file will appear in the list:

  7. Now you have enabled "My namespace" like support in your C# project.

Have fun!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts « Previous page - Next page »