In preparation for the next two posts, I want to offer a cute IDisposable that applies a Stopwatch to whatever body of code it encloses. It is not as robust as it could be (see the TODOs), but here it is for what it's worth.
/// <summary>
/// Times the execution of a body of code.
/// Timing begins when this object is constructed,
/// and ends when it is Disposed.
/// </summary>
public sealed class CodeTimer : IDisposable
{
// Tracks the indent level through nested CodeTimers.
// TODO - Track the indent level by thread ID.
static int _indentLevelStatic;
readonly string _description;
readonly Stopwatch _stopwatch = new Stopwatch();
readonly int _indentLevel;
// Actions that can write the results of this timer.
// TODO - Dependency-inject these Actions.
readonly Action<int, string> _writeStartingMessage = (indentLevel, descr) =>
Console.WriteLine(@"{0}{1}: Starting.", new String(' ', indentLevel * 4), descr);
readonly Action<int, string, TimeSpan> _writeFinishedMessage = (indentLevel, descr, elapsed) =>
Console.WriteLine(@"{0}{1}: Finished in {2:s\.ffff} seconds.", new String(' ', indentLevel * 4), descr, elapsed);
/// <summary>
/// Construct a CodeTimer.
/// </summary>
/// <param name="description">Describes the code being timed.</param>
public CodeTimer(string description)
{
_description = description;
_indentLevel = _indentLevelStatic++;
_writeStartingMessage(_indentLevel, _description);
_stopwatch.Start();
}
/// <summary>
/// Disposes the object and writes the results.
/// </summary>
public void Dispose()
{
_stopwatch.Stop();
_writeFinishedMessage(_indentLevel, _description, _stopwatch.Elapsed);
--_indentLevelStatic;
}
}
In the next post, you'll see the CodeTimer at work.