Da collection
mit der gleichen Rate schrumpft wie rows
, wird Ihre Speicherauslastung stabil bleiben. Der Aufruf gc.collect()
macht keinen großen Unterschied.
Das Speichermanagement in CPython ist subtil. Nur weil Sie Referenzen entfernen und einen Erfassungszyklus ausführen, bedeutet dies nicht unbedingt, dass der Speicher an das Betriebssystem zurückgegeben wird. Siehe diese Antwort für Details .
Um wirklich Speicher zu sparen, sollten Sie diesen Code um Generatoren und Iteratoren statt um große Listen von Elementen strukturieren. Ich bin sehr überrascht, dass Sie sagen, dass Sie Verbindungstimeouts haben, weil das Abrufen aller Zeilen nicht viel mehr Zeit in Anspruch nehmen sollte als das gleichzeitige Abrufen einer Zeile und das Durchführen der einfachen Verarbeitung, die Sie ausführen. Vielleicht sollten wir uns Ihren DB-Abruf-Code ansehen?
Wenn eine row-at-time-Verarbeitung wirklich nicht möglich ist, dann bewahren Sie Ihre Daten zumindest als unveränderliche Deque auf und führen Sie die gesamte Verarbeitung mit Generatoren und Iteratoren durch.
Ich werde diese verschiedenen Ansätze skizzieren.
Zuerst einige allgemeine Funktionen:
%Vor%Nun ist das Ideal eine reihenweise Verarbeitung wie folgt:
%Vor%Dies nimmt die kleinstmögliche Speichermenge - nur eine Zeile nach der anderen.
Wenn Sie wirklich die gesamte Ergebnismenge speichern müssen, können Sie den Code leicht ändern:
%Vor% Nun sammeln wir alle Ergebnisse in collection
first, die für den gesamten Programmlauf vollständig im Speicher bleiben.
Wir können jedoch auch Ihren Ansatz des Löschens von Sammlungselementen bei ihrer Verwendung duplizieren. Wir können dieselbe "Code-Form" beibehalten, indem wir einen Generator erstellen, der seine Quellensammlung so leert, wie sie funktioniert . Es würde ungefähr so aussehen:
%Vor% Jetzt können Sie einfach drain(collection)
für collection
ersetzen, wenn Sie Speicherplatz freigeben möchten. Nachdem drain(collection)
erschöpft ist, ist das collection
-Objekt leer.
Wenn Ihr Algorithmus von der linken Seite oder vom Anfang einer Liste abhängt, können Sie deque Objekt aus Sammlungen als schnellere Alternative.
Zum Vergleich:
%Vor%Drucke:
%Vor% Also ist für diesen speziellen Test des Herausspringens vom Anfang der Liste oder Warteschlange deque
mehr als 10x schneller.
Dieser große Vorteil ist jedoch nur für die linke Seite. Wenn Sie denselben Test mit pop () ausführen, ist die Geschwindigkeit ungefähr gleich. Sie können die Liste auch an der richtigen Stelle umkehren und von der rechten Seite aufspringen, um dieselben Ergebnisse wie von der Deque zu erhalten.
Im Sinne von "Effizienz" wird es viel effizienter sein, einzelne Zeilen aus der Datenbank zu verarbeiten. Wenn das keine Option ist, bearbeiten Sie Ihre Liste (oder Deque) "Sammlung" an Ort und Stelle.
Versuchen Sie etwas in dieser Richtung.
Brechen Sie zuerst die Zeilenverarbeitung aus:
%Vor%Sehen Sie sich nun eine Deque an, um schnelle Pops von links zu ermöglichen:
%Vor%Oder wenn Sie bei einer Liste bleiben möchten:
%Vor%Ich denke, dass Ihr ursprünglicher Ansatz von pop (0), die Zeile verarbeiten und gc alle 5000 Zeilen aufrufen, wahrscheinlich suboptimal ist. Das GC wird automatisch viel öfter automatisch aufgerufen.
Meine letzte Empfehlung:
deque
. Es ist wie ein list
, aber schneller für Links-Push oder Pops; popleft()
, sodass Sie die Liste nicht umkehren müssen (wenn die Reihenfolge von collection
sinnvoll ist); Tags und Links python garbage-collection memory-management