The blog of Eric Sibly; focusing on mountain biking, .NET development for the Desktop, Smartphone and PocketPC.

Thursday, June 09, 2005

Assigning a Nullable.Value is expensive...

Whilst enhancing some existing code today to support Nullable within some highly performant serialization code I noticed a doubling in the serialization times. My tests indicated that the coding resulted in a doubling of the time to perform the serialization on average, it went from 2 milliseconds to 4 per Type to serialize. This is with 25% of the fields being defined as Nullable. Not significant in the overall scheme of things within a total transaction time on the server, but certainly enough to peek my interest to investigate further.

I wrote a little console test app in an attempt to isolate the problem in case I was doing something stupid - which is quite possible ;-) I am using the latest Visual 2005 Beta 2.

The code basically boxes a DateTime/Nullable and then casts each back to the DateTime primitive using a Stopwatch to determine the total ticks. The following is the test code:

private static void PerfTestNullables()
{
PerfTestNullable();
PerfTestNullable();
PerfTestNullable();
}

private static void PerfTestNullable()
{
DateTime dateTime1 = DateTime.Now;
Nullable dateTime2 = DateTime.Now;
Nullable dateTime3 = null;

object obj = dateTime1;
DateTime dt1;
Nullable dt2;

// Test normal DateTime cast.
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
dt1 = (DateTime)dateTime1;

sw.Stop();
Console.WriteLine(sw.ElapsedTicks);

// Test generics cast, HasValue and assignment
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
dt2 = (Nullable)dateTime2;
if (dt2.HasValue)
dt1 = dt2.Value;
}

sw.Stop();
Console.WriteLine(sw.ElapsedTicks);

// Test generics cast and no value (no assignment)
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
dt2 = (Nullable)dateTime3;
if (dt2.HasValue)
dt1 = dt2.Value;
}

sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
}

The results are as follows - I was certainly surprised by the difference - it is significant.

18212   // Test normal DateTime cast.
110856 // Test generics cast, HasValue and assignment
37330 // Test generics cast and no value (no assignment)

18047 // Test normal DateTime cast.
107263 // Test generics cast, HasValue and assignment
44612 // Test generics cast and no value (no assignment)

24410 // Test normal DateTime cast.
108138 // Test generics cast, HasValue and assignment
51104 // Test generics cast and no value (no assignment)

The following MSDN bug has been created.

0 Comments:

Post a Comment

<< Home