Есть ли утечка памяти в реализации ConcurrentBag <T>? [Дубликат]
Possible Duplicate:
Possible memoryleak in ConcurrentBag?
Edit1:
Актуальный вопрос Можете ли вы подтвердить это или мой образец неверен, и мне не хватает чего-то очевидного?
Я думал, что ConcurrentBag - просто замена неупорядоченного списка. Но я был неправ. ConcurrentBag добавляет себя в качестве ThreadLocal к потоку создания, что в основном вызывает утечку памяти.
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 КБ или 100 ГБ в зависимости от того, сколько данных я добавляю в пакеты. Данные, ни сумки уходят.
Когда я врываюсь в это с Windbg, и я делаю ! 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 и его данные будут там до тех пор, пока создающий поток еще жив.
Таким образом, я получил утечку памяти в несколько ГБ. Я сделал "исправить" это с помощью списка и блокировки. ConcurrentBag может быть быстрым, но бесполезен в качестве простой замены для List с тем же временем жизни объекта.
Если я когда-либо создаю ConcurrentBag в главном потоке, я сохраню его, пока он жив. Это не то, чего я ожидал, и это может вызвать сильную боль.