Werden persistente Sammlungen gesammelt?

8

Wenn ich einen Verweis auf einen Teil einer persistenten Sammlung halte, kann die gesamte Sammlung Müll gesammelt werden? Verstehe ich das richtig?

Die Funktion gctest dient nur dazu, das Verhalten von Sammlungen zu testen.

%Vor%

Ich habe schon von Kopfretention gehört, aber das scheint etwas allgemeiner zu sein oder nicht?

Was ich verstehen möchte, ist, wie ich große wechselnde Sammlungen verwenden kann. Ich erwarte, dass sich große Teile der Sammlungen im Laufe der Zeit so verändern, dass große Teile im Prinzip Müll gesammelt werden können, aber nicht alle.

Gibt es einen Standardweg, um damit fertig zu werden?

    
Falko 14.06.2012, 16:33
quelle

2 Antworten

7

Die Standard-GC-Regel bleibt bestehen: Solange Sie den Verweis auf einen Teil der Sammlung beibehalten, bleiben alle Objekte, auf die von Ihren Referenzen zugegriffen werden kann, im Speicher. So ist nur der Teil der Sammlung , auf den von Ihren Referenzen aus zugegriffen werden kann hold , der Rest wird gesammelt. Insbesondere, wenn Sie sich auf die letzten 50 Elemente der Liste mit 100 Elementen beziehen, werden zuerst 50 Elemente gesammelt und der Rest bleibt im Speicher.

In Ihrem Fall werden jedoch alle Elemente jeder Sammlung, beginnend mit 100, beibehalten. Und der Grund dafür ist faule Bewertung . Die Funktion take erzeugt faule Folge von (in Ihrem Fall) 5 Elementen. Das Lazy Sequence-Objekt selbst ist keine echte Sequenz, sondern ein spezielles Generator-Objekt (obwohl es nicht Clojures, sondern Pythons Begriff ist). Wenn Sie Element der verzögerten Sequenz benötigen, generiert das Generatorobjekt es und gibt es zurück. Wenn Sie jedoch nicht nach dem Element fragen, behält der Generator nur Verweise auf alle Objekte, die zum Generieren eines Elements benötigt werden.

In Ihrem Beispiel erstellen Sie einen großen Vektor und fragen nach 5 Elementen und speichern dann das Ergebnis in den Variablen a , b , c usw. Clojure erzeugt ein großes Vektor- und Generatorobjekt und zeigt auf das 100ste Element . Der Verweis auf die Sammlung selbst ist verloren, aber der Verweis auf das Generatorobjekt wird auf der obersten Ebene gespeichert. Sie werten niemals Generator-Objekte aus und erstellen daher niemals echte 5-Element-Sequenzen. REPL bezieht sich auf vars a , b , c usw. Diese Variablen beziehen sich auf Generatorobjekte und Generatorobjekte beziehen sich auf die Sammlungen, die sie benötigen, um echte 5-Element-Sequenzen zu erzeugen. Daher müssen alle Elemente (mit Ausnahme der ersten 100) aller Sammlungen im Gedächtnis bleiben.

Wenn Sie dagegen Generatorobjekte auswerten, erzeugen sie echte 5-Element-Sequenzen und vergessen den Verweis auf den Rest der Sammlung. Versuchen Sie Folgendes:

%Vor%

Es gibt kein OutOfMemory! Vars a , b , c usw. speichern nun echte Listen von 5 Elementen, und somit gibt es keine Referenzen mehr auf große Sammlungen, so dass sie gesammelt werden können.

    
ffriend 14.06.2012, 18:50
quelle
4

Diese Art von Problemen kann mit Lazy-Sequenzen gelöst werden. In Ihrem Fall haben Sie vec function verwendet, die tatsächlich einen Vektor im Speicher erstellt, indem Sie jedes Element durchlaufen, das von der range -Funktion generiert wurde (der Bereich gibt eine verzögerte Sequenz zurück).

Unterhalb des Codes (ohne vec call wird das Speicherproblem nicht auftreten)

%Vor%

AKTUALISIEREN :

Wenn Sie den Aufruf vec verwenden, werden alle Elemente im Speicher beibehalten und nicht per GC gesammelt, da diese Elemente vom Sequenzobjekt referenziert (und benötigt) werden, das von der Funktion gctest zurückgegeben wird hole die benötigten Elemente (dh überspringe 100 Elemente und nehme 5 Elemente), wenn das Sequenzobjekt nach Elementen gefragt wird.

    
Ankur 14.06.2012 16:43
quelle

Tags und Links