I have List collection with 100 million entities in it. When I perform a simple Linq Where()
query, it takes approximately 48 ticks (10,000 ticks = 1ms) for a search, whereas putting 100 million entities in a ConcurrentBag
and then using the same search query on it takes 58 ticks.
I have repeated the test multiple time and the difference remains pretty much the same. Can someone elaborate why is there a performance difference?
From the spec of ConcurrentBag<T>.GetEnumerator
:
The enumeration represents a moment-in-time snapshot of the contents of the bag. It does not reflect any updates to the collection after GetEnumerator was called. The enumerator is safe to use concurrently with reads from and writes to the bag.
Internally, ConcurrentBag
is creating a new list every time you enumerate over it, and additional actions.
From ReferenceSource.microsoft.com:
public IEnumerator<T> GetEnumerator()
{
// Short path if the bag is empty
if (m_headList == null)
return new List<T>().GetEnumerator(); // empty list
bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
return ToList().GetEnumerator();
}
finally
{
UnfreezeBag(lockTaken);
}
}
private List<T> ToList()
{
Contract.Assert(Monitor.IsEntered(GlobalListsLock));
List<T> list = new List<T>();
ThreadLocalList currentList = m_headList;
while (currentList != null)
{
Node currentNode = currentList.m_head;
while (currentNode != null)
{
list.Add(currentNode.m_value);
currentNode = currentNode.m_next;
}
currentList = currentList.m_nextList;
}
return list;
}
Naturally, this must be slower than enumerating over a simple list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With