Ich versuche zu testen, wie die schweren Objekte innerhalb der .net BlockingCollection
behandelt werden.Garbage Collector kann Speicherressourcen nicht wiederherstellen
Ich bekomme die schweren Objekte mit einigen API, und möchte es in mehreren Threads verarbeiten. Um dies zu tun, habe ich einen Thread, der die schweren Objekte liest und sie in mehrere Threads verschiebt, wobei jeder Thread seine eigene blockierende Sammlung hat und jeder dieser Threads das Objekt aus der Sammlung und dem Prozess herausnimmt. Ich erwarte, dass GC, wenn das Objekt aus der gesamten Sammlung entfernt wird, wo immer es sitzt, in der Lage sein sollte, es zu säubern. Das Aufräumen passiert nicht und mein Programm geht aus dem Speicher.
Calling GC.Collect()
dazwischen hilft mir, den Prozess abzuschließen, aber es hat erhebliche Leistungseinbußen, die ich mir nicht leisten kann zu nehmen.
Meine einzige Frage ist, warum Garbage Collector die Ressourcen hier nicht freigeben kann, auch wenn die Objekte nicht in Reichweite sind.
public class DummyProcessor
{
List<BlockingCollection<object>> listOfBlockingCollection = null;
void ProcessCollection(object blockingCollection)
{
BlockingCollection<object> collection = (BlockingCollection<object>)blockingCollection;
while (collection.IsCompleted == false)
{
object heavyObject = collection.Take();
CallExternalProcess(heavyObject);
}
}
private void CallExternalProcess(object heavyObject)
{
throw new NotImplementedException();
}
public void Analyze(object heavyObject)
{
if (listOfBlockingCollection == null)
{
listOfBlockingCollection = new List<BlockingCollection<object>>();
for (int i = 0; i < 25; i++)
{
BlockingCollection<object> coll = new BlockingCollection<object>();
listOfBlockingCollection.Add(coll);
Thread pt = new Thread(new ParameterizedThreadStart(ProcessCollection));
pt.Start(coll);
}
}
for (int i = 0; i < 25; i++)
{
listOfBlockingCollection[i].Add(heavyObject);
}
}
}
Sie sagten 'GC.Collect()' macht es funktioniert, das bedeutet, dass der Garbage Collector die Elemente sammeln kann, ist es nur nicht zu wählen. Haben Sie versucht, einen Speicher-Profiler auf dem Programm auszuführen, bis zu dem Punkt, an dem er mit einem Speicherfehler abstürzt? Vielleicht sind die Objekte nicht außerhalb des Geltungsbereichs, wenn Sie denken, dass sie es sind. Sie fügen allen 25 Sammlungen dasselbe Objekt hinzu. Wenn einer der Threads langsam ausgeführt wird, können alle Objekte, die noch bearbeitet werden müssen, nicht gesammelt werden. Ich bin immer noch neugierig, warum Sie 25 Sammlungen verwenden, die bewirken, dass das gleiche Objekt 25 Mal bearbeitet wird. –
@ScottChamberlain Visual Studio Speicher Profiler läuft schrecklich langsam, wahrscheinlich muss ich es über Nacht laufen lassen. Aber ich bin mir sicher, dass diese Objekte nicht veröffentlicht werden, auch wenn sie aus der Sammlung entfernt wurden. Der Code, den ich zur Verfügung gestellt habe, ist der Überblick darüber, was im Originalcode passiert. Dasselbe Objekt wird zu mehreren Sammlungen hinzugefügt, da jede Sammlung auf ihre eigene Weise verarbeitet und in ihrem eigenen Format in einen anderen Datenspeicher geschrieben wird. – Bikswan
Ich bin ein großer Fan von [dotMemory] (https://www.jetbrains.com/dotmemory/), es kommt mit Resharper, wenn Sie es haben, oder es hat auch eine kostenlose 5-Tage-Testversion, wenn Sie dies nicht tun. –