Saturday, September 05, 2009

C# Timings

Recently, I was adding a bit of debug code to measure how long it took to run various parts of my program (yes, I know a profiler would be more accurate, but I just needed a rough estimate). So, I had 3 or 4 areas in my code where I did something akin to

TimeSpan timer = new TimeSpan();
DateTime startTime = DateTime.Now;
Type1 rval = DoIt(a, b);
timer += DateTime.Now - startTime;

Firstly, this code is ugly. I'm obviously doing many different things here: timing code, calling a function, storing it's result, etc.... It would be much better if I could wrap the timing code into its own function. So, I esentially want something like:

TimeSpam timer = TimeIt( () => DoIt(a, b) );

The code for TimeIt is simple to write

TimeSpan TimeIt(Action a)
{
DateTime startTime = DateTime.Now;
a.Invoke();
return DateTime.Now - startTime;
}

However, that doesn't save the return value of DoIt, so that is useless for my purposes. I need TimeIt to return the value from DoIt. To do this, I make TimeIt a generic method and have it accept a function instead of an action. I pass the TimeSpan in as a reference argument. The calling code looks like

TimeSpan timeSpan = new TimeSpan();
Type1 rValue = TimeIt(() => DoIt(a, b), ref timeSpan);

The TimeIt function looks like

public static T TimeIt(Func f, ref TimeSpan timeSpan)
{
DateTime startTime = DateTime.Now;
T rVal = f.Invoke();
timeSpan += DateTime.Now - startTime;
}

There, now we have a simple and generic way to time a single method that returns a value. If you wanted to go further, you could create a class that held the TimeSpan value so that you wouldn't have to pass it in as a ref, but this worked for my needs and was clean enough so I stopped here. If I need this code again, I'll refactor it into another library and perhaps into its own class. Until then, I'll enjoy the cleanliness and conciseness.

No comments: