Tag Archive for IDisposable

Quick and Dirty Code Timing

When looking to optimize our code, the first and best advice we should keep in mind is this: Measure. Don’t optimize before you know what takes time, and then only optimize where it makes sense.

Measuring can be done in many ways. Using Performance Counters, high-performance timers and stress tests. But often, especially in early iterations, we just want to get a ballpark figure for how long a bit of code takes. Maybe a low-level database call that gets used a lot, maybe as a wrapper in our initialization code to know what should be moved to lazy evaluation. In those cases, the quickest approach is to simply use .NET’s System.Diagnostics.Stopwatch class. Start it, stop it, and print out the timing.

So to ease this common pattern, and to illustrate, once more, the IDisposable pattern I so love to use, here’s a wrapper around Stopwatch, a TimedBlock class that lets you start a new using block around the code you want timed, and have the timing outputted to the Trace listeners. This can be seen in Visual Studio’s Output window, or in any Trace listener you care to add.

Here is the code:

public class TimedBlock : IDisposable { private readonly string _blockName; private readonly Stopwatch _timer; private static int _anonymousBlockCounter = 1; public TimedBlock(string blockName = null, params object[] arguments) { _blockName = !string.IsNullOrEmpty(blockName) ? string.Format(blockName, arguments) : "Anonymous #" + _anonymousBlockCounter++; _timer = new Stopwatch(); _timer.Start(); } public void Dispose() { if (_timer != null && _timer.IsRunning) { _timer.Stop(); Trace.WriteLine(string.Format("{0} took {1} seconds.", _blockName, _timer.Elapsed.TotalSeconds), "Timer"); } }

  public static TimedBlock Start(string blockName = null, params object[] arguments) { return new TimedBlock(blockName, arguments); } }

And here’s the usage:

using (new TimedBlock("Potentially slow action #{0} ", actionId)) {

DoSlowOperation(); }

 

Notes:

  • Just for kicks, I added two ways to initialize the TimedBlock. Either with new TimedBlock() or with TimedBlock.Start(). They are identical, merely stylistically different.
  • The block is initialized with a name. This is used to find it in the trace output. If no name is passed, a default name will be used.

Have fun with it. Remember, it’s just a quick and dirty timesaver. Use it well.