Search code examples
c#multithreadingconcurrent-collections

Is a ConcurrentBag still the proper choice for backing an Object Pool if you know the access pattern will be unfavorable?


After profiling, I've discovered that a specific object in my application will benefit greatly by using an object pool instead of constructing it. This application is based around producer/consumer queues with multiple threads.

The ConcurrentBag collection is basically an ObjectPool, and seems perfect as the backing store for the application's Object Pool. If I understand correctly, the ConcurrentBag conceptually works like this:

  1. Keep a ThreadLocal collection of the bagged objects. Add to this collection when inserting, remove from this collection when removing.
  2. If there are no elements in the local collection and an object must be removed, steal one from another thread's local collection.

The problem is I already know that the application will always request the object on thread 'A', and always return it on thread 'B'. Thus, it will always default to the steal case.

Knowing this access pattern, would it be better to back the object pool with a different collection provided by the framework?


Solution

  • For your use case a ConcurrentQueue would be the better structure to use. As you surmised ConcurrentBag should only really be used when you are primarily inserting and pulling from the same thread, ConcurrentQueue does not have thread affinities.

    Most Producer Consumer models will have separate threads writing and reading, that is why BlockingCollection<T> uses a ConcurrentQueue<T> as its default backing store.