August 20, 2021

Stopwatch Extension

Some simple code to use a Stopwatch class to measure how long a piece of code takes to run. With this extension you can forget about the Stopwatch syntax:

namespace Utilities.StopwatchExtensions
{
  public static class StopwatchExtender
  {
    public static TimeSpan MeasureRunTime(this Action codeToRun)
    {
        var stopWatch = Stopwatch.StartNew();
        codeToRun();
        stopWatch.Stop();
        return stopWatch.Elapsed;
    }
  }
}

From .NET 7.0 you can use this form:

namespace Utilities.StopwatchExtensions
{
  public static class StopwatchExtender
  {
    public static TimeSpan MeasureRunTime(this Action codeToRun)
    {
        long startTime = Stopwatch.GetTimestamp();;
        codeToRun();
        TimeSpan elapsedTime = Stopwatch.GetElapsedTime(startTime);
    }
  }
}
Or put them together
namespace Utilities.StopwatchExtensions
{
  /// <summary>
  /// Stopwatch extension tomeasure the time to perform an Action
  /// </summary>
  /// <example>
  /// <code>
  ///  Action work = () => list = someDb.Get().ToList();
  ///  var timeTakenMs = work.MeasureRunTime().TotalMilliseconds;
  /// </code>
  /// </example>
  public static class StopwatchExtender
  {
    public static TimeSpan MeasureRunTime(this Action codeToRun)
      {
      TimeSpan elapsedTime = TimeSpan.Zero;
#if NET7_0_OR_GREATER
      var startTime = Stopwatch.GetTimestamp();
      codeToRun();
      elapsedTime = Stopwatch.GetElapsedTime(startTime);
#else
      var sw = Stopwatch.StartNew();
      codeToRun();
      sw.Stop();
      elapsedTime = sw.Elapsed;
#endif
      return elapsedTime;
    }
  }
}
Remember to wrap the extension in a specific isolating namespace otherwise the intelli-editor in Visual Studio will get polluted with unused extension methods. To use:
Action codeToRun = () => { /* code whose execution time needs measuring */};
var runTimeMs = codeToRun.MeasureRunTime().TotalMilliseconds;
Trace.WriteLine("*** Time to complete task: " + runTimeMs + " ms");

using (var process = Process.GetCurrentProcess())
{
    Trace.WriteLine($"*** Execution time: {runTimeMs.ToString()} ms");
    Trace.WriteLine($"*** Gen-0: {GC.CollectionCount(0).ToString()}");
    Trace.WriteLine($"*** Gen-1: {GC.CollectionCount(1).ToString()}");
    Trace.WriteLine($"*** Gen-2: {GC.CollectionCount(2).ToString()}");
    Trace.WriteLine($"*** Peak WrkSet: {process.PeakWorkingSet64.ToString("n0")}");
}

No comments: