wtorek, 25 sierpnia 2009

Why should you use generics instead of simple interfaces in method parameters in .NET

Answer: for performance reasons

Consider following methods

public static void TestMax()

{

    int max = (int)Max(5, 10);

}

 

public static object Max(IComparable left, IComparable right)

{

    return left.CompareTo(right) > 0 ? left : right;

}

Now let see how TestMax() is looking when compiled to IL

.method public hidebysig static void TestMax() cil managed
{
.maxstack 2
.locals init ([0] int32 max)
L_0000: nop
L_0001: ldc.i4.5
L_0002: box int32
L_0007: ldc.i4.s 10
L_0009: box int32
L_000e: call object Test.Program::Max(class [mscorlib]System.IComparable, class [mscorlib]System.IComparable)
L_0013: unbox.any int32
L_0018: stloc.0
L_0019: ret
}


So as we can see for this simple call we have two box instructions. This means that we have two heap allocations (malloc() in c).


Now lets see how generic version will behave:




public static void TestMax()



{



    int max = Max(5, 10);



}



 



public static T Max<T>(T left, T right) where T : IComparable



{



    return left.CompareTo(right) > 0 ? left : right;



}




and TestMax() in IL looks like this:



.method public hidebysig static void TestMax() cil managed
{
.maxstack 2
.locals init (
[0] int32 max)
L_0000: nop
L_0001: ldc.i4.5
L_0002: ldc.i4.s 10
L_0004: call !!0 Test.Program::Max<int32>(!!0, !!0)
L_0009: stloc.0
L_000a: ret
}


As you can see instead of box we now have ldc instructions which means that now we are allocating 2*4 bytes on the stack which is much much faster then allocation on the heap.



So the long answer is: Because by this simple tweak you can speed up your method for all struct parameters.

Brak komentarzy: