Problem at hand: an ID generator.
Like many other things, developers can be categorized into three types : *
Now I am definitely not a concurrency guru like myteammates, however when I looked at a code for an ID generator that had
public int GetNextId() {
lock(locker)
return nextId++;
}
I immediately ran a git-checkout, changed that offending piece of code to
public int GetNextId() {
return Interlocked.Increment(ref nextId) – 1;
}
And created a patch to send to the innocent owner of the code.
Smart heh? **
Then I thought that it won’t hurt to throw in a little proof for this amazing improvement.
Running 1000 calls to a GetNextId that was using a lock, took longer than calling the method using Interlocked ! Ah Ha – who’s the man?
Then I realised that a better test will be to run these 100 calls in parallel. That is after all the whole idea of a shared generator. Many threads might need to call it on the same time !
To my surprise, when asking for IDs in parallel, the interlocked construct was almost always slower, taking about 150% of the time the lock construct took on most runs (I tried this again and again, every time averaging 100 repeats).
Here’s a screenshot of the test run
Code is here: https://gist.github.com/24b9012a49392c4e458b
After thinking about this a little, I think that I have an idea why this is happening, assuming my SpawnAndWait call is not entirely stupid (is it?)
So I call you my dear readers (most of which are way smarter than I am): what is your take on that? why did that happen? and would you have chosen lock or interlocked for an ID generator?
** probably not