Precise Execution Timing in C# Using the Stopwatch Class

The System.Diagnostics.Stopwatch type provides a reliable mechanism for measuring elapsed time in .NET applications. It leverages high-resolution performance counters when available on the underlying hardware and OS, falling back to the standard system timer otherwise. The precision and behavior of the timer can be inspected via the static Frequency and IsHighResolution fields.

Core members of the class include:

  • Elapsed: Returns a TimeSpan representing the total measured duration.
  • ElapsedMilliseconds: Provides the total duration as a 64-bit integer in milliseconds.
  • ElapsedTicks: Exposes the raw timer ticks accumulated during measurement.
  • IsRunning: Indicates whether the timer is currently active.
  • StartNew(): Factory method that instantiates, resets, and immediately begins timing.
  • Start() / Stop(): Controls the measurement state without clearing accumulated time.
  • Reset(): Halts timing and clears the elapsed duration.
  • Restart(): Combines Reset() and Start() into a single operation.
  • GetTimestamp(): Retrieves the current raw tick count from the underlying timer mechanism.

Under the hood, Stopwatch counts ticks from the hardware or system timer. The relationship between ticks and seconds is defined by Stopwatch.Frequency. To convert raw ticks to seconds, divide ElapsedTicks by Frequency.

The folllowing example demonstrates a typical measurement workflow, encluding state checks and duration extraction:

using System;
using System.Diagnostics;
using System.Threading;

public class PerformanceMonitor
{
    public static void MeasureOperation()
    {
        var timer = Stopwatch.StartNew();

        // Simulate workload
        Thread.Sleep(150);

        timer.Stop();

        TimeSpan duration = timer.Elapsed;
        long millis = timer.ElapsedMilliseconds;
        long rawTicks = timer.ElapsedTicks;
        bool active = timer.IsRunning;

        Console.WriteLine($"Duration: {duration}");
        Console.WriteLine($"Milliseconds: {millis}");
        Console.WriteLine($"Raw Ticks: {rawTicks}");
        Console.WriteLine($"Timer Active: {active}");
        Console.WriteLine($"System Frequency: {Stopwatch.Frequency} ticks/sec");
        Console.WriteLine($"High Resolution: {Stopwatch.IsHighResolution}");

        // Resume and reset demonstration
        timer.Restart();
        Thread.Sleep(50);
        timer.Stop();
        Console.WriteLine($"Second interval (ms): {timer.ElapsedMilliseconds}");
    }
}

Duration values returned by Stopwatch.Elapsed are represented as TimeSpan structures. A TimeSpan models a time interval using days, hours, minutes, seconds, and fractional seconds. The fundamental unit of a TimeSpan is a tick, where one tick equals 100 nanoseconds. The structure's value range spans from TimeSpan.MinValue to TimeSpan.MaxValue.

Standard string formatting for TimeSpan follows the pattern [-]d.hh:mm:ss.ff. The optional leading minus sign denotes negative intervals. The d component tracks full days, while hh, mm, ss, and ff represent hours (00-23), minutes, seconds, and fractional seconds respectively. Because months and years have variable lengths, TimeSpan deliberately caps its largest unit at days to ensure consistent arithmetic. For instance, a TimeSpan initialized with 10_000_000_000_000 ticks formats as 11.13:46:40, translating to 11 days, 13 hours, 46 minutes, and 40 seconds.

Tags: C# .NET Performance Profiling System.Diagnostics TimeSpan

Posted on Fri, 30 Oct 2026 16:42:37 +0000 by axtg86