Search code examples
c#.netperformanceconcurrencyconcurrent-collections

Performance comparison of ConcurrentBag vs List


Preface: I'm only asking this because I don't have an environment (dataset large enough + computing power) to test it in a reliable fashion.

Question: Given a ConcurrentBag<T>, loaded with billions of items, being accessed/used by a single thread, does it perform similar to a List<T>? Putting in another words, is the enumeration over a ConcurrentBag<T> any more or less performatic than over a List<T>?


Solution

  • ConcurrentBag<T> will inevitably be less performant than List<T>. Although you will only be accessing it from a single thread, the structure still needs to have mechanisms in place to protect against the possibility of race hazards should concurrent access arise.

    If you will be loading the collection from a single thread before starting your enumerations, you can avoid the performance overhead by using the ConcurrentBag(IEnumerable<T>) constructor, rather than adding each item individually through its Add method.

    ConcurrentBag<T> provides “moment-in-time snapshot” semantics for enumerations; see the remarks for its GetEnumerator method. When you access ConcurrentBag<T> from a foreach loop, it will first copy its entire contents into a plain List<T>, then enumerate over that. This will incur a substantial performance overhead (both computation- and memory-wise) each time you use it in a loop.

    If your scenario is that your list will be populated by multiple threads, but then only read by one thread, then you should convert it to a List<T> as soon as the writers are done.