有没有在ConcurrentBag℃的内存泄漏; T>实施?内存、ConcurrentBag、GT

2023-09-04 01:53:26 作者:正在缓冲

可能重复:   在ConcurrentBag 可能memoryleak?

Possible Duplicate: Possible memoryleak in ConcurrentBag?

EDIT1:

实际问题。你能否证实这还是我的样本错了,我失去了财产以后明显?

The actual question is. Can you confirm this or is my sample wrong and I am missing somthing obvious?

我还以为ConcurrentBag是的simpy可以代替unorderd列表。但是我错了。 ConcurrentBag确实自身添加为ThreadLocal中,以创建线程这也基本上是造成内存泄露。

I have thought that ConcurrentBag is simpy a replacement for an unorderd list. But I was wrong. ConcurrentBag does add itself to as ThreadLocal to the creating thread which does basically cause a memory leak.

   class Program
    {
        static void Main(string[] args)
        {
            var start = GC.GetTotalMemory(true);
            new Program().Start(args);
            Console.WriteLine("Diff: {0:N0} bytes", GC.GetTotalMemory(true) - start);
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            Thread.Sleep(5000);
        }

        private void Start(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            { 
                var bag = new ConcurrentBag<byte>();
                bag.Add(1);
                byte by;
                while (bag.TryTake(out by)) ;
            }
        }

我可以做的Diff 250 KB或100 GB取决于有多少数据我添加到包。该数据也袋子走了。

I can make Diff 250 KB or 100 GB depending on how much data I add to the bags. The data nor the bags go away.

当我打入这个与WinDBG的,我做了 !DumpHeap型并发

When I break into this with Windbg and I do a !DumpHeap -type Concurrent

...

000007ff00046858        1           24 System.Threading.ThreadLocal`1+GenericHolder`3[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib]]
000007feed812648        2           64 System.Collections.Concurrent.ConcurrentStack`1[[System.Int32, mscorlib]]
000007feece41528        1          112 System.Collections.Concurrent.CDSCollectionETWBCLProvider
000007ff000469e0     1000        32000 System.Threading.ThreadLocal`1+Boxed[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]]
000007feed815900     1000        32000 System.Collections.Concurrent.ConcurrentStack`1+Node[[System.Int32, mscorlib]]
000007ff00045530     1000        72000 System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]]

当我创建一个空的ConcurrentBag让一些工作线程将数据添加到它ConcurrentBag及其数据将在那里只要创建线程仍然活着。

When I do create an empty ConcurrentBag to let some worker threads add data to it ConcurrentBag and its data will be there as long as the creating thread is still alive.

这样,我得到了几个GB的内存泄漏。我没有修复这个用列表和锁。 ConcurrentBag可能是快,但它是无用的简单替代具有相同对象的生命周期的List。

This way I got a several GB memory leak. I did "fix" this by using a List and locks. ConcurrentBag may be fast but it is useless as simple replacement for a List with the same object lifetime.

如果我曾经创建主线程上ConcurrentBag我会保持它只要线程处于活动状态。这不是我所期望的,它可以引起严重的疼痛。

If I ever create a ConcurrentBag on the main thread I will keep it as long as the thread is alive. This is not something I would expect and it can cause major pain.

推荐答案

您说的没错,ConcurrentBag创建一个ThreadLocal副本,其实他们是为场景,相同的线程读取和写入数据包优化。 .. ConcurrentBag是线程安全的包实施,对于场景相同的线程将是既生产和消费存储收入囊中的数据进行了优化。

You are right that ConcurrentBag creates a ThreadLocal copy, in fact they are optimized for scenarios where the same thread is reading and writing the data to the bag: "... ConcurrentBag is a thread-safe bag implementation, optimized for scenarios where the same thread will be both producing and consuming data stored in the bag."

在otherhand,我没有看到一个奇怪的行为在这里;螺纹生活和并发袋生活。当线程完成GC将做的工作。

On the otherhand, I do not see a strange behaviour here; the thread lives and the concurrent bag lives. When thread finishes GC will do it's job.