Stopwatch on Interlocked.Increment(ref x) vs. lock (y) { x++; }
Given 10 million iterations:
object y = new object();
const int iterations = 10000000;
Which is faster, InterlockedIncrement:
stopWatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
Interlocked.Increment(ref x);
}
stopWatch.Stop();
Console.WriteLine("Interlocked took " + stopWatch.ElapsedMilliseconds);
Or lock:
stopWatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
lock (y)
{
x++;
}
}
stopWatch.Stop();
Console.WriteLine("lock took " + stopWatch.ElapsedMilliseconds);
The answer surprised me:
Interlocked took 168
lock took 389
Best,
Brian
Comments
- Anonymous
July 24, 2009
Nice examples...here after i will need to use this method!!Also until now i have used StopWatch at all! (i never knew about it!)Now i know .net is Ocean..long way to swim!!(earlier we used timespan to count the difference in time!) stopwatch is simple & great! - Anonymous
July 24, 2009
It's not so surprising when you learn how they are implemented.A lock involves a lot of stuff -- some extra object overhead and at least two of its own Interlocked operations.Interlocked.Increment is implemented in literally a single multi-proc-safe atomic instruction of "LOCK INC" or "LOCK XADD". It will also be much more scalable -- try running it in parallel on four cores and the perf difference will be even greater. - Anonymous
July 24, 2009
Oh, I agree. I just expected the performance with 0 contention to be closer because I knew lock was based, in part, on interlocked operations. - Anonymous
August 21, 2009
Actually if you use volatile instead, its even better. - Anonymous
August 31, 2009
@hunterb46: A volatile x++ is not thread-safe. x++ involves a volatile read from x, then incrementing that value and a volatile write to write it back. It may be faster, but if two threads overlap at that instruction, you'll lose one increment.