Wann werden Objekte in Python in den Müll geworfen? Wann wird der Speicher freigegeben und hat die Sammlung Auswirkungen auf die Leistung? Kann man den Garbage-Collection-Algorithmus abschalten oder anpassen und wenn ja, wie?
Antworten
Zu viele Anzeigen?Wann werden Objekte in Python in den Müll geworfen?
Der Quellcode von CPython ist sehr detailliert: http://svn.python.org/view/python/trunk/Modules/gcmodule.c?revision=81029&view=markup
Sobald die Anzahl der Verweise auf Null sinkt, wird das Objekt sofort entfernt.
293 /* Pythons zyklisches gc sollte niemals einen eingehenden refcount sehen
294 * von 0: Wenn etwas auf 0 dekrementiert wird, sollte es auch
295 * zu diesem Zeitpunkt sofort wieder freigegeben werden.
Eine vollständige Sammlung wird ausgelöst, wenn die Anzahl der neuen Objekte mehr als 25 % der Anzahl der vorhandenen Objekte beträgt.
87 Zusätzlich zu den verschiedenen konfigurierbaren Schwellenwerten, lösen wir nur eine
88 vollständige Sammlung, wenn das Verhältnis
89 langlebig_ausstehend / langlebig_insgesamt
90 über einem bestimmten Wert liegt (fest verdrahtet auf 25%).
Wann wird der Speicher freigegeben?
Ich konnte nur diese Informationen herausfischen.
781 /* Alle freien Listen löschen
782 * Alle freien Listen werden bei der Abholung der höchsten Liste geleert. Generation gelöscht.
783 * Zugewiesene Elemente in der freien Liste können eine pymalloc-Arena behalten besetzt halten.
784 * Das Löschen der freien Listen kann dem Betriebssystem früher Speicher zurückgeben.
785 */
Demnach kann es sein, dass Python Ihr Objekt in einer freien Liste zum Recyceln behält, auch wenn Sie seine Refcount auf Null reduzieren. Ich bin nicht in der Lage, explizit herauszufinden, wann der free-Aufruf erfolgt, um Speicher an das Betriebssystem zurückzugeben, aber ich nehme an, dass dies immer dann geschieht, wenn eine Sammlung durchgeführt wird und das Objekt nicht in einer free-Liste gehalten wird.
Wirkt sich die Sammlung auf die Leistung aus?
Jeder nicht-triviale Garbage Collector, von dem ich gehört habe, benötigt sowohl CPU als auch Speicher, um zu funktionieren. Daher gibt es in der Tat immer Auswirkungen auf die Leistung. Sie müssen experimentieren und Ihren Garbage Collector kennen lernen.
Bei Programmen, die eine Echtzeit-Reaktion erfordern, habe ich Probleme, da die Garbage Collectors mir keine Kontrolle darüber geben, wann sie laufen oder wie lange sie laufen. In einigen besonderen Fällen kann es auch zu übermäßigem Speicherverbrauch kommen, z. B. durch Pythons Fähigkeit, freie Listen zu führen.
Hier ist ein Auszug aus der Sprachreferenz
Objekte werden nie explizit zerstört; wenn sie jedoch unerreichbar werden, können sie in den Müll wandern. Eine Implementierung darf die Garbage Collection verschieben oder ganz auslassen - es ist eine Frage der Implementierungsqualität, wie die Garbage Collection implementiert wird, solange keine Objekte gesammelt werden, die noch erreichbar sind.
CPython-Implementierung im Detail : CPython verwendet derzeit ein Referenz-Zählschema mit (optionaler) verzögerter Erkennung von zyklisch verknüpftem Müll, das die meisten Objekte sammelt, sobald sie unerreichbar werden, aber nicht garantiert, dass Müll mit zirkulären Referenzen gesammelt wird. Siehe die Dokumentation des gc-Moduls für Informationen über die Kontrolle der Sammlung von zyklischem Müll. Andere Implementierungen handeln anders und CPython kann sich ändern. Verlassen Sie sich nicht auf die sofortige Finalisierung von Objekten, wenn sie unerreichbar werden (z.B.: schließen Sie immer Dateien).
EDIT: Über die Verschiebung der Garbage Collection .... die gc
Modul können Sie mit dem Garbage Collector interagieren und ihn bei Bedarf deaktivieren, die Häufigkeit der Sammlung ändern usw. Aber ich habe es selbst nicht benutzt. Außerdem enthalten Zyklen, die irgendwelche Objekte mit __del__
Methoden werden nicht gesammelt .
Um die vorherigen Antworten mit einigen weiteren Zahlen und umsetzbaren Informationen zu ergänzen:
Sie können verwenden gc.set_threshold(threshold0[, threshold1[, threshold2]])
um einzustellen, wann die automatische Garbage Collection einsetzt:
Der GC teilt Objekte in drei Generationen ein, je nachdem, wie viele Sammlungsdurchläufe sie überlebt haben. Neue Objekte werden in die jüngste Generation (Generation 0) eingeordnet. Wenn ein Objekt eine Sammlung überlebt wird es in die nächst ältere Generation verschoben. Da die Generation 2 die die älteste Generation ist, verbleiben die Objekte in dieser Generation nach einer Sammlung. Um zu entscheiden, wann er ausgeführt werden soll, verfolgt der Kollektor die Anzahl der Objektzuweisungen und -freigaben seit der letzten Sammlung. Wenn die Anzahl der Zuweisungen minus der Anzahl der Deallokationen den Schwellenwert0 überschreitet, beginnt die Abholung. Anfänglich werden nur Generation 0 untersucht. Wurde die Generation 0 mehr als Schwellenwert1 mehr als einmal untersucht wurde, seit die Generation 1 untersucht wurde, dann wird die Generation 1 ebenfalls untersucht. Bei der dritten Generation sind die Dinge etwas komplizierter, siehe Sammeln der ältesten Generation für mehr Informationen.
Ich konnte die Standardschwellenwerte zwar nicht in der Dokumentation finden, aber wenn ich mir die Implementierung ansehe, sind die Standardwerte für die Schwellenwerte zu sein scheinen (CPython 3.9.1) :
threshold0
: 700threshold1
: 10threshold2
: 10
D.h. standardmäßig sollte die automatische Garbage Collection einsetzen, wenn die Anzahl der Allokationen minus der Anzahl der Deallokationen 700 überschreitet.