Seite 1 von 1
Objekt wird nicht vom GarbageCollector eingesammelt
Verfasst: Mittwoch 21. April 2010, 12:26
von cmFBDD
Hey Jungs und Mädels,
ich bin totaler Anfänger in Sachen Python und habe ein Problem mit dem GarbageCollector. Um bestimmte Moleküle zu erstellen, benutze ich Pybel. Um dann zu checken, ob diese Moleküle ein bestimmtes Molekulargewicht überschreiten, habe ich eine kleine Funktion gebastelt, die ein Objekt (OBMol) aus einem String erzeugt, aus dem dann das Molekulargewicht genau errechnet werden kann.
Code: Alles auswählen
def getMolWtBool(combined_smile):
mol = pybel.readstring("smi", combined_smile)
return not (mol.molwt > 502.01588)
Wenn ich nun meinen Boolean habe, würde ich normalerweise davon ausgehen, dass Python das Objekt mol verwirft und den Speicher freimacht. Leider ist das nicht der Fall, denn mit größeren Inputdatenmengen steigt der Arbeitsspeicherverbrauch enorm. Andere Fehlerquellen konnte ich bisher ausschließen, denn wenn ich das "aufräumen" erzwinge, scheint er das Objekt zu beseitigen. Diese Variante scheint mir aber die schlechteste.
Re: Objekt wird nicht vom GarbageCollector eingesammelt
Verfasst: Mittwoch 21. April 2010, 12:31
von Hyperion
cmFBDD hat geschrieben:
Wenn ich nun meinen Boolean habe, würde ich normalerweise davon ausgehen, dass Python das Objekt mol verwirft und den Speicher freimacht. Leider ist das nicht der Fall, denn mit größeren Inputdatenmengen steigt der Arbeitsspeicherverbrauch enorm.
Selbst wenn Python das Objekt nicht löschen würde, würde es bei jedem Funktionsaufruf doch überschrieben. Insofern kann es doch gar nicht an dieser Stelle einen Fehler geben - außer die Factoryfunktion beinhaltet das Leck...
Prinzipiell sollte das Objekt aber zum Löschen freigegeben werden, sobald die Funktion abgearbeitet ist. Das wäre zumindest mein Verständnis.
Verfasst: Mittwoch 21. April 2010, 14:52
von DasIch
Die Funktion hat kein Leak. pybel.readstring könnte allerdings eins haben.
Verfasst: Donnerstag 22. April 2010, 07:35
von cmFBDD
Erstmal Danke!
Das bedeutet, wenn der Fehler dort liegt, kann ich wenig ausrichten mit meinen Laienhaften Kenntnissen... ???
Verfasst: Donnerstag 22. April 2010, 09:40
von Hyperion
cmFBDD hat geschrieben:Erstmal Danke!
Das bedeutet, wenn der Fehler dort liegt, kann ich wenig ausrichten mit meinen Laienhaften Kenntnissen... ???
Naja, Du könntest Dir die Funktion mal angucken, nach einer neueren Version gucken, prüfen, ob so ein Bug schon gemeldet wurde und ggf. die Entwickler kontaktieren.
Zudem hast Du uns ja nur einen kleinen Teil gezeigt. Evtl. ist das Problem ja auch ganz woanders bei Dir.
Du könntest auch mal ein
minmales Beispiel hier posten, damit wir das ggf. nachvollziehen können

Verfasst: Donnerstag 22. April 2010, 20:26
von cmFBDD
Also ich habe nochmal etwas rumgesucht und es gibt da leider wirklich ein
Problem mit Pybel (oder eher mit Openbabel).
"Memory leak in OBConversion_ReadString - ID: 2978796" sogar ganz aktuell!
http://sourceforge.net/tracker/?func=de ... tid=428740
Ich komme leider nicht um diese Funktion Readstring drum herum! Und daher habe ich mir nun 2 Möglichkeiten überlegt:
1. Ich brauch das Mol-Objekt genau 2 mal an verschiendenen Stellen und muss es auch aus einem String erzeugen! Ich könnte diese beiden Funktionen einfach in 2 Scripte extra schreiben und dann per subprocess aufrufen und die Ergebnisse über die Pipeline abfangen... Dauert aber glaub ich zu lange bei großen Datenmengen...
2. Ich weiß nicht ob sowas machbar ist: Vielleicht könnte ich ein Objekt, indem fall das Mol-Objekt, aus dem Arbeitsspeicher in einen File schreiben...
Habt ihr da Vorschläge????
Verfasst: Donnerstag 22. April 2010, 23:47
von jerch
Dein erster Vorschlag wäre ein gangbarer Workaround, wenn auch hässlich. Evtl. wäre auch das Modul [mod]multiprocessing[/mod] was für Dich, dann könntest Du den "Leseprozess" mehrmals benutzen und ihn beenden, wenn der Footprint zu groß wird und so den Speicher wieder frei geben.
Dein zweiter Vorschlag funktioniert nur, wenn Du zwischendurch den lesenden Python-Prozess beendest, was wohl noch unpraktikabler sein dürfte.
Besser wäre es natürlich, das Speicherleck zu fixen. Ich hab mir den Quellcode mal angeschaut (allerdings nur überflogen), tatsächlich wird in der beschiebenen Methode Speicher reserviert und ein Pointer hierauf zurückgegeben. Ein bool-Flag soll die spätere nötige Freigabe anzeigen. Hier müßte man auf Callerebene mal schauen, ob das auch für alle Fälle beachtet wird.
Komisch ist die zurückgebene Methode Read. Ist die gzip-Prüfung erfolgreich, so wird `pInStream` dereferenziert einem zip_istream übergeben und anschliessend an `pInStream` gebunden. Das sieht nach einem möglichen Speicherleck aus.
Verfasst: Freitag 23. April 2010, 13:54
von cmFBDD
Also ich habe mal rumprobiert mit der Variante Multiprocess, aber so richtig gefallen tut mir das nicht! Verzögert den ohnehin schon sehr langsamen Prozess nur noch.
Meinst du es ist so schwer den Fehler zu fixxen? Ich habe leider glaub ich wirklich zu wenig Know-how um da ranzugehen.
Verfasst: Freitag 23. April 2010, 22:28
von jerch
Ohne genauere Kenntnis des Codes und dessen Funktionsweise ist es schwierig, so etwas zu fixen. Da fährst Du mit einem ausführlichen Bugreport besser.
Ich habe mich trotzdem mal hingesetzt und das Beispiel auf der Bugreportseite zurückverfolgt und gleich 2 Speicherlecks gefunden:
Code: Alles auswählen
diff -upr openbabel-2.2.3/src/formats/smilesformat.cpp patched/src/formats/smilesformat.cpp
--- openbabel-2.2.3/src/formats/smilesformat.cpp 2009-07-31 19:28:36.000000000 +0200
+++ patched/src/formats/smilesformat.cpp 2010-04-23 22:57:25.000000000 +0200
@@ -820,7 +820,12 @@ namespace OpenBabel {
public:
OBSmilesParser() { }
- ~OBSmilesParser() { }
+ ~OBSmilesParser() {
+ map<OBAtom*,TetrahedralStereo*>::iterator iter;
+ for(iter=_tetrahedralMap.begin(); iter!=_tetrahedralMap.end(); ++iter) {
+ delete iter->second;
+ }
+ }
bool SmiToMol(OBMol&,const string&);
bool ParseSmiles(OBMol&);
diff -upr openbabel-2.2.3/src/obconversion.cpp patched/src/obconversion.cpp
--- openbabel-2.2.3/src/obconversion.cpp 2009-06-26 19:41:05.000000000 +0200
+++ patched/src/obconversion.cpp 2010-04-23 22:34:37.000000000 +0200
@@ -271,6 +271,7 @@ namespace OpenBabel {
pOutStream=NULL;
NeedToFreeOutStream = false;
}
+ delete pLineEndBuf;
}
//////////////////////////////////////////////////////
Das erste Leck ist tief im smile-Parser vergraben. Hier wird im Falle eines '@' im smile-String eine STL map<> mit Pointern erstellt. Der Speicher wird allerdings von C++ nicht automatisch freigegeben, daher die explizite Version. Ich bin mir in keinster Weise darüber im Klaren, wo die Freigabe genau zu erfolgen hat, dafür fehlt mir der Überblick über die Funktionsweise des Parsers und des OBMol-Konstruktes. Hier muß in jedem Falle ein Entwickler drüber schauen.
Das zweite Leck scheint ein vergessener Pufferpointer von pInputStream in OBConversion zu sein, den hab ich mal dem Destructor hinzugefügt. Auch hier wiederum keine Garantie bzgl. Nebeneffekten.
Mit den obigen Änderungen läuft das Bsp. ohne Speicherleck durch (funktioniert auch mit dem Python-binding).
Allerdings glaube ich, dass in openbabel noch mehr Lecks versteckt sind (zb. die gzip-Sache war mir noch aufgefallen, habs aber nicht getestet). Insgesamt wirkt in den Quelldateien der Umgang mit 'new' etwas abenteuerlich.
Vllt. hilft Dir das ja weiter und Du kannst hieraus einen vernünftigen Bugreport erstellen.
Grüsse jerch
Edit:
Falschen Patch eingestellt

Verfasst: Sonntag 25. April 2010, 12:03
von cmFBDD
WOW Danke!!!
Also ich habe mir das ganze angesehen und verstehe was du gemacht hast. Für meine Bedürfnisse wird dieser HotFix glaub ich vollkommen reichen!
Jetzt muss ich nur noch das ganze auch unter Windows umgesetzt bekommen... weil Openbabel habe ich einfach mit dem WindowsInstaller installiert!
Aber nochmals Danke! Das ganze Brauch ich nämlich für meine Bachelorarbeit und jetzt nochmal alles mit anderen Mitteln umsetzen, hätte einfach zu viel Zeit gekostet!
Verfasst: Donnerstag 29. April 2010, 17:26
von cmFBDD
Hey Jerch,
nochmals vielen Dank für deine Bemühungen. Sag mal, du konntest ja die Änderungen am Source sogar ausprobieren... Hast du das ganze unter Linux gebaut? Hast du nach der Anleitung im Wiki gearbeitet? Ich bekomm es unter Windows gar nicht erst deployed Sad
Gruß der Chris
Verfasst: Donnerstag 29. April 2010, 19:19
von jerch
Ja ich nutze hier Opensuse, mit dem Dreisatz hatte ich es lokal installiert und konnte die Lecks mit einer Mischung aus Valgrind und printf-Debugging relativ schnell ausfindig machen. Von einer Anleitung in einem Wiki weiss ich nichts. Übrigens ist das Speicherleck im Parser in der SVN-Version behoben, dafür gibts neue zu entdecken
Wo klemmts denn bei Dir? Wenn ich mich recht entsinne, lagen den Quelldateien Projektmappen für VS2005 und 2008 bei, vllt. gibt es da aber ein paar Dinge bzgl. des Compilers zu beachten. Läuft denn wenigstens der Build der Bibliothek durch? Dann könntest Du das ja in C++ umsetzen. Für das Python-Binding brauchst Du dann noch SWIG und die Python-includes, hier mußt Du ggf. darauf achten, dass die Libs kompatibel zueinander sind (im Zweifelsfalle denselben Compiler benutzen).
Poste doch mal den Anfang der Fehlermeldung.
Grüsse jerch
Verfasst: Freitag 30. April 2010, 18:01
von cmFBDD
Na das Bauen mit Visual 2008 ergab keine Errors. Mit der Anleitung für 2005 gabs nur Probleme! Habe sogar die GUI mit WXwidget compiled...
Ich habe jetzt mal nen Installer gebaut mit dem NISI-Tool... bis auf ein Warning gab es da auch keine Probleme... Wenn ich jetzt den Installer benutze hat er beim import von Pybel in Python einen Fehler im swig_import_helper.... _mod referenced before assignment.... glaube aber nicht, dass das am Script liegt sondern eher, dass ich nochmal die Pythonbindings bauen muss! dazu gibt es aber keinerlei Dokumentation und die ausm Wiki kann ich nicht umsetzen da im Trunk die Daten so nicht mehr vorhanden sind...
und sowas nennt man dann Bioinformatiker ;-P
Verfasst: Montag 3. Mai 2010, 05:50
von jerch
Welche Version hast Du denn jetzt gebaut? SVN trunk?
Mit dieser habe ich das Python-Binding nicht gebaut, nur mit der 2.2.3. Das Makefile ist dort nur für die Lib zuständig, das Python-Binding liess sich aber problemlos mit 'python setup.py build' aus dem Python-Ordner heraus bauen. Keine Ahnung, inwieweit das im trunk umgestellt wurde und Du hier irgendeinen cmake-Schalter benutzen musst oder ob der 'setup.py build'-Weg noch funktioniert. Der Fehler deutet zumindest darauf hin, dass etwas mit dem C++-Teil des SWIG-Modules nicht stimmt. Ist das denn mit kompiliert worden? (Du musst es auf jeden Fall irgendwo erstellen, sonst fehlt es ja gänzlich.) Stimmen die Pfade?
Mehr als vage Vermutungen und Fragen habe ich hier im Moment auch nicht.
Meld Dich nochmal, falls Du da nicht weiterkommst, ich würde dann bei Gelegenheit nochmal draufschauen, 4 Augen sehen bekanntlich mehr als 2...
Grüsse jerch
Verfasst: Montag 3. Mai 2010, 09:57
von cmFBDD
Ich habe mich erst mal nicht weiter damit beschäftigt! Stattdessen habe ich mal das Multiprozessing ausprobiert und das ist ja recht easy! Allerdings für sehr große Simulationen mit meinem Programm, denk ich doch nicht geeignet, dass es die Laufzeit doch stark beeinflußt!
Also werde ich mir heut nachmittag nochmal ansehen was genau beim bauen von Openbabel 2.3.0 noch fehlt!
Die Variante mit der Installation der Bindings funktionierte auch nicht! Da fehlte ihm irgendwas... muss ich mir heute nachmittag aber nochmal ansehen, da ich es nur aufm Heimrechner habe....
Verfasst: Montag 3. Mai 2010, 19:17
von cmFBDD
Hey also... ich habe es mal versucht wie, also die bindings über "python setup.py install" zu installieren! Da fehlt ihm die openbabel-python.cpp! Die glaub ich erhalt ich wenn ich die windowsOBF speziel OBPythonOBF baue! Dabei fehlt ihm aber die BabelConfig.h! Diese ist zwar auch im Buildordner vorhanden aber die findet er trotzdem nicht!
Weiß echt nicht wie ich das machen soll...
Verfasst: Dienstag 4. Mai 2010, 01:56
von jerch
So gehts mit VS2005 und openbabel 2.2.3:
- openbabel Projektmappe mit VS öffnen (unter openbabel-2.2.3\windows-vc2005)
- benötigte include/lib/bin-Pfade setzen, das sind im einzelnen (hab hoffentlich keinen vergessen):
- include: Pfad zu zlib.h
- include: Pfad zu Python.h (wird mit dem Windows-binary mitgeliefert)
- lib: Pfad zu pythonXX.lib
- bin: Pfad zum SWIG binary
- Rechtsklick auf OBPythonOBF --> Erstellen
- Warten (Kaffeetrinken)
Im Ordner openbabel-2.2.3\windows-vc2005\OBPythonOBF\dist findest Du dann das fertige Pythonpaket als Installer.
Dem Paket fehlen allerdings die DLLs. Die könntest Du entweder mit einem selbstgestrickten Installer (z.B. fürs "große" Openbabel) mitliefern oder an das setup.py-Skript anhängen (quasi als standalone-Pythonversion).
Das zu-Fuss-Bauen an der Konsole geht unter Windows natürlich auch, würde ich Dir aber nicht empfehlen, da das zur unnötigen Pfadjongliererei wird und es mit VS so schön vorkonfiguriert ist.
Verfasst: Dienstag 4. Mai 2010, 11:22
von cmFBDD
also ich habe nochmal das ganze mit VC 2008 gebaut... und auch den Installer gebaut... wieder das selbe! Die Vorgängerversion OB-2.3.0s1 (vom 02.04.2010) ausm Netz macht genau die selben Probleme, also _mod referenced before...
wenn ich jetzt beispielsweise "import _openbabel" in Python benutze sagt er mir DLL load failed!
Welche DLL-Dateien aus dem Build brauch ich denn und wo müssen die hin?
Verfasst: Mittwoch 5. Mai 2010, 11:02
von jerch
Ich hab im Moment keine Zeit, das nochmal mit der SVN-Version zu testen. Vllt. gegen Ende der Woche...
cmFBDD hat geschrieben:Welche DLL-Dateien aus dem Build brauch ich denn und wo müssen die hin?
Ein kurzer Blick in die
Projektdatei zeigt folgende Abhängigkeiten:
Code: Alles auswählen
../OBDLL.lib;../OBConv.lib;../OBDESC.lib;../oberror.lib;../obcommon.lib
Wo die DLLs liegen müssen, damit Windows sie finden kann, steht
hier.