What is the performance penalty incurred by adding the C# Stop Watch to an object?
-
Why, are you experiencing performance problems when adding it? – Oded Mar 29 '12 at 12:45
-
14You can benchmark the penalty using a seccond stopwatch ;) – Pop Catalin Mar 29 '12 at 12:45
-
1I'd create a micro-benchmark using a stopwatch, to time it :) – Rob Levine Mar 29 '12 at 12:45
-
Damn - @PopCatalin - beat me by 6 seconds. – Rob Levine Mar 29 '12 at 12:46
-
I have some sample profiling info on one of my questions: http://stackoverflow.com/questions/9825178/profiling-net-applications-with-stopwatch – Kendall Frey Mar 29 '12 at 12:48
-
@Pop: I actually did just that in the question mentioned. – Kendall Frey Mar 29 '12 at 12:49
-
1What you do with the *results* of the Stopwatch timings (logging the times to a file, Debug.WriteLine, etc.) will probably take far longer than the Stopwatch itself. – Joe White Mar 29 '12 at 12:59
-
1@PopCatalin - And then add a third stopwatch to benchmark the second stopwatch. – Steve Wellens Mar 29 '12 at 13:01
-
3@SteveWellens Turtles, all the way down. – asawyer Mar 29 '12 at 13:06
-
@SteveWellens asawyer It's stopwatch-ception! – Bob2Chiv Mar 29 '12 at 13:12
3 Answers
Since I desired to use some timing statistics in an object creation pool to optimize its performance on-the-fly, I needed to know if adding a Stopwatch
to monitor the timing would adversely affect the performance of the object creation. I wanted to time a typical object creation (appr. 20-30 ms) to optimize the timeout for the Task creating them, but only if adding the Stopwatch
did not noticeably slow down the loop.
So I wrote this test program to separately time the overhead of creation, Start()
, Stop()
and elapsed time retrieval of the Stopwatch
.
using System;
using System.Diagnostics;
namespace SO9925598_Stopwatch_overhead
{
class Program
{
private const int nLoops = 10000;
private const double nLoopsDouble = nLoops;
private const int waitTime = 2; //ms
static void Main(string[] args)
{
Stopwatch stopwatchTimingTheTest = new Stopwatch();
double frequencyConversionFactor = 1000.0 / Convert.ToDouble(Stopwatch.Frequency); // ms per click
Stopwatch stopwatchUnderTest;
// Instantiation
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest = new Stopwatch();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest = null;
}
long elapsed = stopwatchTimingTheTest.ElapsedTicks;
double overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Creation overhead {overhead} ms per Stopwatch instantiation. (Based on {nLoops} trials).");
// Further tests can all use the same object
stopwatchUnderTest = new Stopwatch();
// Start
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Start() overhead {overhead} ms.");
// Stop
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Stop() overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedTicks;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedTicks overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedMilliseconds;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedMilliseconds overhead {overhead} ms.");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
These were the results:
Creation overhead 0,00011756 ms per Stopwatch instantiation. (Based on 10000 trials).
Stopwatch.Start() overhead 0,000256 ms.
Stopwatch.Stop() overhead 0,00023665 ms.
Stopwatch.ElapsedTicks overhead 0,00010946 ms.
Stopwatch.ElapsedMilliseconds overhead 0,00011758 ms.
The times are the average time per single call of the method based on 10000 samples.
The program was running on a machine with Intel Core i7-8850H CPU at 2.60 GHz with Windows 10 operating system.
Conclusion: for my application where the object creation is 20-30 ms the overhead of the Stopwatch
is negligible.

- 1,442
- 9
- 18
Should not be that significant in the context of C# programming. If it proves to be significant, reconsider your need/use of Stopwatch and C#.
You can always try to benchmark it yourself by implementing it 1000 times, timing it, and then dividing the results by 1000. It's difficult to say precisely how performance demanding this feature is, but you could compare it to some other simple operations and see how it relates to.

- 1,179
- 2
- 13
- 32
-
2I did this and got 0.258 milliseconds, on average, to both instantiate with Stopwatch.StartNew and measure with .ElapsedMilliseconds. This was in debug mode, local, on a reasonably fast machine. – Abacus Jul 05 '16 at 19:56
static void Main(string[] args)
{
Worker(1); // jit Warmup
var stopWatchOfStopwatchStopwatch = System.Diagnostics.Stopwatch.StartNew();
var stopWatchOfLoop = System.Diagnostics.Stopwatch.StartNew();
Worker(100000000);
stopWatchOfLoop.Stop();
Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
stopWatchOfStopwatchStopwatch.Stop();
Console.WriteLine("Elapsed of outer SW: " + stopWatchOfStopwatchStopwatch.Elapsed.ToString());
var stopwatchOfcompareLoop = System.Diagnostics.Stopwatch.StartNew();
Worker(100000000);
stopwatchOfcompareLoop.Stop();
Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
}
static void Worker(int iterations)
{
for (int i = 0; i < iterations; i++)
{
Console.WriteLine("bla");
}
}
The difference is insignificant - but that pretty much depends on your performance goals :)

- 7,901
- 1
- 41
- 56
-
Please quanity "significant." Does that mean a few seconds, milliseconds, etc.? – Kevin Meredith Mar 29 '12 at 13:17
-
For 5000 iterations on my Quad Core 2.83 GHZ, 8 GB Ram and x64 Win7, it was at the order of 0.000XXX seconds. – Alex Mar 29 '12 at 13:55