Tigraine

Daniel Hoelbling-Inzko talks about programming

DRY Guard clause performance

Posted by Daniel Hölbling on June 6, 2009

Brad Wilson left me an inspiring comment on my post about his Guard class that I immediately tried out:

If you target 3.5, you could write a guard which used expressions, and then you could evaluate the expression in order to fill things out. Unfortunately, the syntax ends up a little wonky, but at least you’re not repeating yourself:

Guard.ArgumentNotNull(() => username);

You could also do the same thing with complex expressions:

Guard.Precondition(() => username.Length > 10);

and when you throw the exception, it can even contain the actual condition code, extracted from the expression.

I went off to implement this using an Expression and ended up with the following ArgumentNotNull method:

public static void ArgumentNotNull(Expression<Func<object>> action)
{
    var result = action.Compile()();
    if (result == null)
    {
        //TODO: Extract memberinfo name from expression
        throw new ArgumentException();
    }
}

One thing to keep in mind is that guard clauses usually end up being in production code, and not in test code. So performance isn’t neglect able. Since action.Compile() clearly indicates that some compiling overhead happens to retrieve the value, I thought it might be interesting to benchmark it. Just in case it might still be neglect able.

So, I wrote the following tester:

using System;
using System.Diagnostics;
using System.Linq;

public class Program {     private static int passes = 10000;

    private static void Main(string[] args)     {         var runs = 5;         Console.WriteLine("{0} ms to run normal", AverageExecutionTime(RunSimple, runs));         Console.WriteLine("{0} ms to run with expression", AverageExecutionTime(RunExpressions, runs));         Console.ReadLine();     }

    private static long AverageExecutionTime(Action delegateToWatch, int runs)     {         var lapTimes = new long[runs];         for (var i = 0; i < runs; i++)         {             lapTimes[i] = GetExecutiontime(delegateToWatch);         }         return lapTimes.Sum(p => p)/runs;     }

    private static long GetExecutiontime(Action delegateToWatch)     {         var stopwatch = new Stopwatch();         stopwatch.Start();         delegateToWatch();         stopwatch.Stop();         return stopwatch.ElapsedMilliseconds;     }

    private static void RunSimple()     {         for (int i = 0; i < passes; i++)         {             string user = "test";             Guard.ArgumentNotNull("user", user);             GC.Collect();         }     }

    private static void RunExpressions()     {         for (int i = 0; i < passes; i++)         {             string user = "test";             Guard.ArgumentNotNull(() => user);             GC.Collect();         }     } }

As you can see, I rerun the test 4 times doing the NotNull test only 10000 times (always running the non-exceptional path), always forcing garbage collection between passes.

The results were stunning:

image

I ran the test on my 2x3.16 Ghz Intel with 8gb Ram running Windows Vista x64 with no debugger attached and it turned out the expression tree compilation took almost 1 ms per pass. (Without garbage collection normal runs took 0 ms)

Now one could argue, no sane person would place those guards inside some tight loop. But once you run into recursive method calls you may end up creating a performance bottleneck.

Now, since I’m a lazy guy, I ended up writing a Resharper Live template that saves me the repetitive typing:

Guard.ArgumentNotNull("$parametername$", $parametername$);
$END$

Filed under net, programmierung
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more