Search code examples
c#performanceconcurrent-collections

Do concurrent collections cache the enumerator snapshots?


If I understood correctly, then the concurrent collections create a snapshot as a source for the Enumerator used in a foreach loop, which requires locking.

Do they cache the snapshots or lock every time? Does this have a potential performance impact? I'm sceptical about micro-measurements, because they so easily lead to false conclusions and am trying to understand the inner workings.

Thanks!


Solution

  • No, it doesn't appear to cache. Here's the code from ConcurrentBag<T>:

    public IEnumerator<T> GetEnumerator()
    {
        if (m_headList != null)
        {
            bool lockTaken = false;
            try
            {
                FreezeBag(ref lockTaken);
                return ToList().GetEnumerator();
            }
            finally
            {
                UnfreezeBag(lockTaken);
            }
        }
        return new List<T>().GetEnumerator();
    }
    
    private List<T> ToList()
    {
        List<T> list = new List<T>();
        for (ThreadLocalList threadLocalList = m_headList; threadLocalList != null; threadLocalList = threadLocalList.m_nextList)
        {
            for (Node node = threadLocalList.m_head; node != null; node = node.m_next)
            {
                list.Add(node.m_value);
            }
        }
        return list;
    }