Speicherfreigabe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
casio90
User
Beiträge: 4
Registriert: Freitag 6. November 2015, 16:51

Hallo,

ich habe das Problem, dass Python meinen Speicher nicht mehr frei gibt. Ich habe ein Modul geschrieben, dessen Interface in Python ist und dann wird alles nach C/C++ geschoben, dort berechnet und dann nach Python zurueckgegeben. Diese Berechnung braucht so 300 MB. Jetzt will ich einen Benchmark machen und mehrere Parametereinstellungen testen. Folgender Beispielcode:

Code: Alles auswählen

result_list = []
for i in xrange(n):
	foo = MyModule(parameter1, parameter2, i)
	result = foo.compute_stuff()
	result_list.append(result)
evaluate_result(result_list)
Das Problem ist, dass der Speicher, welcher von dem foo-Object in jeder Iteration jeweils angefordert wurde, nicht frei gegeben wird. Das Modul MyModule hat einen Destructor welcher dann alles in C/C++ loescht. Es macht leider keinen Unterschied ob ich das Object am Ende einer Iteration per del loesche, es auf None setzte und oder gc.collect() aufrufe.
Kann mir hier wer helfen? Vielen Dank schon mal.

Gruss,

casio
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Dokumentation zu __del__ -> __del__ ist alles andere als deterministisch, am Besten das Ganze mit einem with-Statement lösen: `__enter__` legt Daten an, `__exit__` löscht sie wieder.
the more they change the more they stay the same
casio90
User
Beiträge: 4
Registriert: Freitag 6. November 2015, 16:51

Ich habe zunehmend den Eindruck, dass der Speicher zwar freigegeben wird, allerdings geht er nicht ans OS zurueck. In der naechsten Iteration wird dann aber neuer Speicher angefordert und nicht der alte, freie, verwendet. Hilft __enter__ und __exit__ da auch?
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@casio90: was ist ein Modul? Module kann man ja nicht mit Parametern initialisieren. Meinst Du in Wirklichkeit Klasse? Ist diese Klasse jetzt reines Python? Dann wird der Speicher automatisch freigegeben, wenn es keine Referenz mehr auf dieses Objekt gibt, würde bei Deinem einfachen Beispiel bedeuten, dass result noch eine Referenz auf foo enthält. Ist MyModule in C++ geschrieben, dann muß der Destructor allen in C++ angeforderten Speicher wieder freigeben. Ohne den Quelltext zu kennen, können wir dann natürlich nicht sagen, ob das tatsächlich passiert, oder ob Du das nur glaubst.

@Dav1d: bei C-Extensions ist es normal, dass es einen Destructor gibt. Context-Manager helfen hier nicht weiter.
BlackJack

@casio90: Vorweg mal Begrifflichkeiten: `MyModule` ist kein Modul sondern eine Klasse. Module kann man nicht aufrufen.

Wie sehen denn die Ergebnisse von `compute_stuff` aus? Können da eventuell noch referenzen auf Objekte bestehen die dadurch am Leben gehalten werden?

Das mit `__del__()` stimmt in soweit man nur Python schreibt. Wenn man Erweiterungen in C schreibt muss man sich natürlich über das Aufräumen hinter einem Objekt Gedanken machen für Ressourcen die Python nicht kennt. Da kommt es jetzt aber auch darauf an wie man externen Code einbindet.

Bist Du sicher das Du allen Speicher wieder frei gibst der nicht unter der Kontrolle von Python steht? Insbesondere im nicht in Python geschriebenen Teil muss man aufpassen.

Ob Speicher den man freigibt wieder dem Betriebssystem zurückgegeben wird, hängt stark vom System beziehungsweise der verwendeten C-Laufzeitbibliothek ab. Das ist also keine Python-Frage. Andererseits gibt's in (C)Python bei der Speicherverwaltung auch ein paar Besonderheiten wie ”memory pools“ für bestimmte Datentypen um das häufige anlegen und zerstören von Objekten zu beschleunigen.

`__enter__()` und `__exit__()` sind einfach nur zwei Methoden die mit ``with`` zusammenarbeiten. Wobei das hilft oder nicht entscheidest Du als Programmierer. Wobei ich bei Objekten die externe Ressourcen verwalten trotzdem auch über das Aufräumen ohne `__exit__()` nachdenken würde. *Wenn* ein Python-Objekt zerstört wird, sollte keine Ressource belegt bleiben.
casio90
User
Beiträge: 4
Registriert: Freitag 6. November 2015, 16:51

Nun gut, ich meinte eine Klasse welche in einem von mir geschrieben Modul ist. Den ganzen Quelltext hier zu posten wuerde den Rahmen deutlich sprengen, das sind mittlerweile wohl so 10.000 Zeilen, alles relevante in C++ nur das Interface ist in Python. Ich wuehle mich mal durch meine Destructoren.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Sirius3 hat geschrieben:@Dav1d: bei C-Extensions ist es normal, dass es einen Destructor gibt. Context-Manager helfen hier nicht weiter.
Hört sich für mich so an als würde der Konstruktor in MyModul über ctypes/cffi Speicher reservieren und `__del__` soll den wieder freigeben. Wenn ich jetzt nicht warte bis `__del__` passiert sonder explizit sage der Speicher soll wieder freigegeben werden, wieso sollte das dann nicht funktionieren? Natürlich kann ich statt einem Context-Manager auch eine `cleanup()` Methode implementieren ...
the more they change the more they stay the same
Antworten