In diesem SO-Thread habe ich gelernt, dass ich eine Referenz halte Bei einer seq
für eine große Sammlung wird verhindert, dass die gesamte Sammlung als Müll gesammelt wird.
Erstens, dieser Thread stammt aus dem Jahr 2009. Ist das in "modernem" Clojure (v1.4.0 oder v1.5.0) immer noch richtig?
Zweitens, gilt dieses Problem auch für Lazy-Sequenzen? Würde% ce_de% beispielsweise zulassen, dass der Garbage Collector die ersten (def s (drop 999 (seq (range 1000))))
-Elemente der Sequenz zurücknimmt?
Schließlich gibt es eine gute Möglichkeit, dieses Problem für große Sammlungen zu umgehen. Mit anderen Worten, wenn ich einen Vektor von, sagen wir, 10 Millionen Elementen hätte, könnte ich den Vektor so konsumieren, dass die verbrauchten Teile Müll gesammelt werden könnten? Was wäre, wenn ich eine Hashmappe mit 10 Millionen Elementen hätte?
Der Grund, warum ich frage, ist, dass ich mit ziemlich großen Datensätzen arbeite, und ich muss vorsichtiger sein, um Referenzen auf Objekte nicht zu behalten, so dass die Objekte, die ich nicht brauche, Müll gesammelt werden können. So wie es ist, finde ich in einigen Fällen einen 999
Fehler.
Es ist immer so, dass Clojure gezwungen ist, alles im Gedächtnis zu behalten, wenn Sie eine Sequenz "am Kopf halten". Es hat keine Wahl: Sie behalten immer noch einen Hinweis darauf.
Das "GC-Overhead-Limit erreicht" ist jedoch nicht dasselbe wie ein Speichermangel-Fehler - Es ist wahrscheinlicher, dass Sie eine fiktive Workload ausführen, die Objekte so schnell erstellt und verschrottet, dass sie den GC hineintricksen zu denken, dass es überlastet ist.
Siehe:
Wenn Sie eine tatsächliche Arbeitslast auf die verarbeiteten Elemente anwenden, werden Sie vermutlich feststellen, dass dieser Fehler nicht mehr auftritt. Sie können in diesem Fall einfach Lazy-Sequenzen verarbeiten, die größer sind als der verfügbare Speicher.
Konkrete Sammlungen wie Vektoren und Hashmaps sind jedoch eine andere Sache: Sie sind nicht faul und müssen daher immer vollständig im Gedächtnis behalten werden. Wenn Sie Datensätze haben, die größer als der Arbeitsspeicher sind, haben Sie folgende Optionen:
Wenn Sie den Kopf einer Sequenz in einer Bindung halten, dann sind Sie richtig und es kann nicht gc'd sein (und das ist bei jeder Version von Clojure). Wenn Sie eine große Menge an Ergebnissen verarbeiten, warum müssen Sie den Kopf festhalten?
Um es herum, ja! lazy-seq-Implementierung kann Teile, die bereits "verarbeitet" wurden und nicht direkt innerhalb der Bindung referenziert werden. Stellen Sie nur sicher, dass Sie nicht den Kopf der Sequenz halten.
Tags und Links memory garbage-collection clojure memory-management