Search

Sunday, August 17, 2008

Back to Basic: Using a System.Threading.Interlocked is a great idea

Bound to give you diabetes :)

I just saw some code which actually takes a lock to do a simple set operation. This is bad because taking locks are expensive and there is an easy alternative. The System.Threading.Interlocked class and its members can get the same job done and much faster.

I wrote the following two methods which increments a variable a million times. The first method does that by taking a lock and the other uses the Interlocked.Increment API.

static int IncrementorLock()
{
int val = 0;
object lockObject = new object();
for (int i = 0; i < 1000000; ++i)
{
lock (lockObject)
{
val++;
}
}

return val;
}

static int IncrementorInterlocked()
{
int val = 0;
for (int i = 0; i < 1000000; ++i)
{
System.Threading.
Interlocked.Increment(ref val);
}

return val;
}

-


I then used the Visual Studio Team System Profiler (instrumented profiling) and got the following performance data.















Function NameElapsed Inclusive TimeApplication Inclusive Time
IncrementorInterlocked()1,363.45134.43
IncrementorLock()4,374.23388.69


Even though this is a micro benchmark and uses a completely skewed scenario, it still drives the simple point that using the interlocked class is way faster.


The reason the interlocked version is faster is because instead of using .NET locks it directly calls Win32 apis like InterlockedIncrement which ensures atomic updation to variables at the OS scheduler level.


These Interlocked APIs complete depend on the support of the underlying OS. This is the reason you'd see that all the APIs are not available uniformly across all versions of .NET (e.g. there is no uniform coverage over WinCE and Xbox). While implementing these for the Nokia platform (S60) we are hitting some scenarios where there is no corresponding OS API.

No comments: