Simplify Time Measurement in Tests and Debug Code
A simple helper class I derived from a more generic pattern: For debugging and testing, I quite often want to measure the time used for a given process. Usually, this looks somewhat like this:
public void TestElapsedTime() { DateTime start = DateTime.Now; //do some work DateTime end = DateTime.Now; double elapsedTime = end.Subtract(start).TotalMilliseconds; Console.Out.WriteLine("Work took {0} milliseconds", elapsedTime); }
However: The code above, while being pretty simple, can be easily wrapped into a generic helper class:
/// <summary> /// A guard that can be used to measure the time /// used for a given process by simply wrapping it /// in a using statement. /// </summary> public class TimeGuard : IDisposable { private readonly Action<double> action; private readonly DateTime startTime; /// <summary> /// Creates the guard with a given action that receives the /// elapsed time in milliseconds. /// </summary> /// <param name="setDelta">The action that is being invoked /// with time (in milleconds) that was taken between construction /// of this instance until disposal.</param> /// <exception cref="ArgumentNullException">If <paramref name="setDelta"/> /// is a null reference.</exception> public TimeGuard(Action<double> setDelta) { if (setDelta == null) throw new ArgumentNullException("setDelta"); action = setDelta; startTime = DateTime.Now; } /// <summary> /// Calculates the elapsed time since construction /// and submits the delta to the <see cref="action"/> /// action. /// </summary> public void Dispose() { var now = DateTime.Now; action(now.Subtract(startTime).TotalMilliseconds); } }
Using the TimeGuard class, I can perform time measurements without having to deal with DateTime instances and the calculation of the elapsed time at all. Two samples:
public void TestElapsedTime() { double elapsedTime = 0; using (new TimeGuard(t => elapsedTime = t)) { //do some work } Console.Out.WriteLine("Work took {0} milliseconds", elapsedTime); }
[Test] public void TestElapsedTime() { using (new TimeGuard(t => Assert.Less(t, 500))) { //do some work here that should take less than 500 ms } }
Apart from providing cleaner code, I also prefer this approach because it encapsulates time measurement functionality in a single class and simplifies adjustments, like using a different pattern to retrieve time stamps, or using the StopWatch class to get a more accurate measurement (thanks to Simone Chiaretta for the hint).
You should use the StopWatch class instead of the DateTime since it’s a more precise timer and doesn’t have the same activation cost that might influence the actual timing.
Simone,
Thanks for your comment – I’ve included a link to the StopWatch class in the article. As a matter of fact, I’m using neither of these – my own implementation relies on a variant of Ayende’s SystemTime class (see link in the article) but I felt the sample in the article is more accessible for most readers.
But that’s the nice thing about encapsulation – it only takes you a few seconds to switch to your own implementation
Cheers,
Philipp
A very cunning use of IDisposable! I also quite like the way you use an action to invoke an Assert. Very cunning indeed
Colin E.
thx Colin
Simone’s already observed that you should use StopWatch (and she’s right). However, if you’re going to stick with DateTime.Now you should really switch it to DateTime.UtcNow. The non-UTC version is hideously slow (use Reflector to look at the code it manages to end up invoking if you don’t believe me).