Czy występuje przeciek pamięci w implementacji ConcurrentBag <T>? [duplikować]
Możliwy duplikat:
Możliwa pamięć pamięci w ConcurrentBag?
Edytuj1:
Rzeczywiste pytanie brzmi: Czy możesz to potwierdzić, czy moja próbka jest błędna i brakuje mi czegoś oczywistego?
Pomyślałem, że ConcurrentBag jest prostym zamiennikiem nieuporządkowanej listy. Ale byłem w błędzie. ConcurrentBag dodaje się jako wątek lokalny do wątku tworzącego, co zasadniczo powoduje wyciek pamięci.
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)) ;
}
}
Mogę zrobić Diff 250 KB lub 100 GB w zależności od ilości danych dodanych do toreb. Dane ani torby nie odchodzą.
Kiedy włamuję się do tego z Windbg i wykonuję! 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]]
Kiedy tworzę pustą torbę ConcurrentBag, aby niektóre wątki robocze dodawały do niej dane, ConcurrentBag i jej dane będą tam, dopóki wątek tworzący wciąż będzie żył.
W ten sposób dostałem przeciek pamięci o pojemności kilku GB. Naprawiłem to, używając Listy i blokad. ConcurrentBag może być szybki, ale jest bezużyteczny jako prosty zamiennik listy o tym samym czasie życia obiektu.
Jeśli kiedykolwiek utworzę ConcurrentBag na głównym wątku, zachowam go tak długo, jak długo wątek żyje. To nie jest coś, czego bym się spodziewał i może spowodować poważny ból.