Bitte beachten Sie die nächste Antwort durch die bessere Lösung @joeblog.
Zuerst sollten Sie nicht alle RAM an erster Stelle benötigen. Was Sie hier tun sollten, ist das Holen Chunks der Ergebnismenge. Tun Sie keine fetchall()
. Verwenden Sie stattdessen die viel effizientere Methode cursor.fetchmany
. Siehe the psycopg2 documentation.
Nun, die Erklärung dafür, warum es nicht freigegeben wird, und warum das kein Speicherverlust in der formal korrekten Verwendung dieses Begriffs ist.
Die meisten Prozesse geben Speicher nicht an das Betriebssystem zurück, wenn es freigegeben wird, sie stellen es nur für die Wiederverwendung an anderer Stelle im Programm zur Verfügung.
Speicher kann nur dann an das Betriebssystem freigegeben werden, wenn das Programm die verbleibenden im Speicher verstreuten Objekte komprimieren kann. Dies ist nur möglich, wenn indirekte Handle-Verweise verwendet werden, da sonst das Verschieben eines Objekts bestehende Zeiger auf das Objekt ungültig machen würde. Indirekte Referenzen sind ziemlich ineffizient, insbesondere bei modernen CPUs, bei denen die Verfolgung von Zeigern schreckliche Dinge an die Leistung bringt.
Was normalerweise passiert, wenn das Programm keine besondere Vorsicht walten lässt, ist, dass jeder große Speicherplatz, der mit brk()
belegt ist, mit ein paar kleinen Stücken belegt ist.
Das Betriebssystem kann nicht feststellen, ob das Programm diesen Speicher noch verwendet oder nicht verwendet, so dass er es nicht einfach zurückfordern kann. Da das Programm nicht dazu tendiert, auf den Speicher zuzugreifen, tauscht das Betriebssystem es normalerweise im Laufe der Zeit aus und gibt den physischen Speicher für andere Zwecke frei. Dies ist einer der Gründe, warum Sie Swap Space haben sollten.
Es ist möglich, Programme zu schreiben, die Speicher an das Betriebssystem zurückgeben, aber ich bin mir nicht sicher, ob Sie das mit Python machen können. auch
Siehe:
Also: Das ist nicht wirklich ein Speicher Leck. Wenn Sie etwas anderes machen, das viel Speicher verwendet, sollte der Prozess nicht viel wachsen, wenn überhaupt, er wird den zuvor freigegebenen Speicher der letzten großen Zuweisung wiederverwenden.
Danke! Bestätigt, dass Speicher erneut verwendet wird, indem der obige Code zweimal im selben Prozess ausgeführt wird. Der Speicher stieg während des zweiten Laufs nicht an. –
Während hier alles richtig ist, wird ein Abfrageergebnis normalerweise vollständig auf der Clientseite übertragen (nicht durch 'fetch *()', sondern durch 'execute()'). Wenn also 'fetchmany()' anstelle von 'fetchall()' verwendet wird, kann beim Erstellen von Python-Objekten etwas Speicher gespart werden. Die Verwendung eines serverseitigen Cursors, wie von @joeblog vorgeschlagen, ist die richtige Lösung. – piro