Existe um vazamento de memória na implementação ConcurrentBag <T>? [duplicado]
Duplicata Possível:
Possível memoryleak no ConcurrentBag?
Edit1:
A questão real é. Você pode confirmar isso ou a minha amostra está errada e eu estou sentindo falta de algo óbvio?
Eu pensei que ConcurrentBag é simpy um substituto para uma lista unorderd. Mas eu estava errado. ConcurrentBag se adiciona como ThreadLocal ao thread de criação que basicamente causa um vazamento de memória.
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)) ;
}
}
Eu posso fazer Diff 250 KB ou 100 GB, dependendo da quantidade de dados que eu adiciono aos sacos. Os dados nem as malas desaparecem.
Quando eu começo isso com o Windbg e eu faço um! 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]]
Quando eu crio um ConcurrentBag vazio para permitir que alguns threads de trabalho adicionem dados a ele, ConcurrentBag e seus dados estarão lá, desde que o thread de criação ainda esteja ativo.
Dessa forma, recebi vários vazamentos de memória GB. Eu fiz "consertar" isso usando uma lista e bloqueios. ConcurrentBag pode ser rápido, mas é inútil como uma substituição simples para uma lista com o mesmo tempo de vida do objeto.
Se eu criar um ConcurrentBag no thread principal, eu o manterei enquanto o thread estiver ativo. Isso não é algo que eu esperaria e pode causar grandes dores.