2 Stimmen

Garbage Collection in einer Linq-Abfrage

Ich habe eine Frage dazu, wie die Garbage Collection in einer Linq-Abfrage behandelt werden könnte. Angenommen, ich habe eine Liste von Anfragen zu verarbeiten. Jede Anfrage erzeugt einen sehr großen Datensatz, aber dann wird ein Filter angewendet, um nur kritische Daten von jeder angeforderten Last zu behalten.

//Input data
List<request> requests;
IEnumerable<filteredData> results = requests.Select(request => Process(request)).Select(data => Filter(data));

Ich weiß also, dass die Abfrage für jedes Datenelement aufgeschoben wird, bis jedes gefilterte Datenelement angefordert wird, also ist das gut. Aber bleibt dieser mittlere speicherintensive Teil bestehen, bis die Aufzählung abgeschlossen ist?

Was ich hoffe, passiert ist, dass jedes Datenelement Garbage Collect werden kann, sobald es die gefilterte Stufe passiert, so dass sichergestellt wird, dass ich genug Speicher, um die gesamte Liste zu verarbeiten haben. Ist dies der Fall, oder hält die mittlere enumerable alles um, bis die gesamte Abfrage endet? Wenn ja, gibt es eine Linq-Möglichkeit, damit umzugehen?


Hinweis: Die Funktion Process() generiert die speicherintensiven Daten... das ist es, worüber ich mir Sorgen mache

4voto

Reed Copsey Punkte 536986

Solange der Rückgabewert von Process(...) y Filter(...) keine Verweise auf die intern verwendeten "großen Datenelemente" enthalten, dann sollte der in diesem Prozess verwendete Speicher nach der Verarbeitung jedes Elements entwurzelt und ein Kandidat für GC werden.

Das bedeutet nicht, dass es gesammelt wird, sondern nur, dass es ein Kandidat ist. Wenn der Speicherdruck hoch wird, wird der GC sie höchstwahrscheinlich sammeln.

4voto

Mark Byers Punkte 761508

Der Garbage Collector ist in .NET recht aggressiv und kann Zwischenobjekte aufräumen aufräumen, wenn sie nicht mehr referenziert werden, sogar innerhalb von Schleifen. In einigen Fällen wird er sogar ein Objekt bereinigen, auf das noch verwiesen wird, wenn er erkennen kann, dass nie wieder darauf zugegriffen wird.

Die Ausführung dieses Codes zeigt, dass die Objekte recht schnell aufgeräumt werden und nicht herumhängen, bis die Abfrage abgeschlossen ist (was sie nie tut):

public class MyClass1 { ~MyClass1() { Console.WriteLine("Cleaned up MyClass1"); } }
public class MyClass2 { ~MyClass2() { Console.WriteLine("Cleaned up MyClass2"); } }

public class Program
{
    static IEnumerable<MyClass1> lotsOfObjects()
    {
        while (true)
            yield return new MyClass1();
    }

    static void Main()
    {
        var query = lotsOfObjects().Select(x => foo(x));
        foreach (MyClass2 x in query)
            query.ToString();
    }

    static MyClass2 foo(MyClass1 x)
    {
        return new MyClass2();
    }
}

Ergebnis:

Cleaned up MyClass1
Cleaned up MyClass1
Cleaned up MyClass1
Cleaned up MyClass2
Cleaned up MyClass2
Cleaned up MyClass1
Cleaned up MyClass2
etc...

1voto

Adam Robinson Punkte 176996

Es ist schwierig, Ihre Frage zu beantworten, da das, was Sie gepostet haben, nicht wirklich kompiliert werden kann ( Select erzeugt eine IEnumerable<T> zu, aber Sie ordnen es einem List<T> . Unter der Annahme, dass die Filter(data) Funktion gibt eine filteredData müssten Sie anrufen ToList() auf die Abfrage, um sie zu speichern in results ).

requests ist, wie ich annehme, bereits mit Daten bestückt. Diese Liste wird den normalen Regeln der Garbage Collection folgen. Ich nehme an, dass das, worüber Sie sich Sorgen machen, das Ergebnis der Process Funktion. Ich kann nicht genau sagen, was passieren wird, weil ich auch keine Ahnung habe, was Ihre Filter Funktion tut. Es sei denn, das Ergebnis der Filter Funktion behält einen Verweis auf ihren Parameter (mit anderen Worten, das Ergebnis der Process Funktion), dann werden die Objekte, die von Process wird nach Abschluss der Abfrage vollständig aus dem Anwendungsbereich entfernt und folgt den normalen Regeln der Garbage Collection.

Beachten Sie, dass diese Regeln Folgendes regeln Förderungswürdigkeit zur Abholung. Es ist nicht garantiert, dass während der Laufzeit Ihrer Anwendung jemals Objekte abgeholt werden. Die Ergebnisse sind jedoch förderfähig, so dass die GC fähig um sie zu sammeln.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X