ConcurrentDictionary<> performance at a single thread misunderstanding?

Royi Namir picture Royi Namir · Mar 6, 2013 · Viewed 22.6k times · Source

Related brief info:

AFAIK , The concurrent stack, queue, and bag classes are implemented internally with linked lists.
And I know that there is much less contention because each thread is responsible for its own linked list. Any way , my question is about the ConcurrentDictionary<,>

But I was testing this code :(single thread)

Stopwatch sw = new Stopwatch();
sw.Start();

    var d = new ConcurrentDictionary < int,  int > ();
    for(int i = 0; i < 1000000; i++) d[i] = 123;
    for(int i = 1000000; i < 2000000; i++) d[i] = 123;
    for(int i = 2000000; i < 3000000; i++) d[i] = 123;
    Console.WriteLine("baseline = " + sw.Elapsed);

sw.Restart();

    var d2 = new Dictionary < int, int > ();
    for(int i = 0; i < 1000000; i++)         lock (d2) d2[i] = 123;
    for(int i = 1000000; i < 2000000; i++)   lock (d2) d2[i] = 123;
    for(int i = 2000000; i < 3000000; i++)   lock (d2) d2[i] = 123;
    Console.WriteLine("baseline = " + sw.Elapsed);

sw.Stop();

Result : (tested many times, same values (+/-)).

baseline = 00:00:01.2604656
baseline = 00:00:00.3229741

Question :

What makes ConcurrentDictionary<,> much slower in a single threaded environment ?

My first instinct is that lock(){} will be always slower. but apparently it is not.

Answer

Jon Skeet picture Jon Skeet · Mar 6, 2013

Well, ConcurrentDictionary is allowing for the possibility that it can be used by multiple threads. It seems entirely reasonable to me that that requires more internal housekeeping than something which assumes it can get away without worrying about access from multiple threads. I'd have been very surprised if it had worked out the other way round - if the safer version were always faster too, why would you ever use the less safe version?