DoNuT
04-03-2008, 14:37
Hi leute,
jo, es ist mein erster post hier, und gleich mit nem ganz dicken problem...
und zwar (soviel kann ich wohl sagen), wir entwickeln software für ein embedded-gerät mit nem arm-prozessor und nicht allzuviel speicher, hier treten aber ein paar probleme auf...
ich versuch mal, das grob zu umreißen...
ein großer teil der funktionalität unserer anwendung ist, von dem gerät (okay, ein RFID-reader) daten zu akquirieren, daraus nen fette xml-textmessage zu machen und diese periodisch an einen beliebigen abnehmer übers netzwerk rauszusenden... ist dieser abnehmer nicht verfügbar, puffern wir die messages bis zu einem bestimmten grad (z.b. 1200 kb freier RAM), darunter hören wir auf, da man nur mehr den stecker am gerät ziehen kann, wenn der speicher volläuft...
verbindet sich der abnehmer, sollten die gepufferten nachrichten eigentlich rausgeblasen werden und würden uns erwarten, dass der speicherverbrauch im großen und ganzen auf das niveau "vor dem sturm" zurückginge, was eben nicht passiert...
es bleibt ein großer batzen hängen - laut /proc/meminfo oder dem gebrauch von sysinfo... wir wissen, dass aufgrund des speichermanagements von linux die sache mit dem "wirklich" freien speicher keine so einfache milchmädchenrechnung ist, weil ungenutzte speicherbereiche noch einem prozess zugeordnet bleiben, solange kein anderer darauf angewiesen ist - deswegen wundert man sich auch oft, warum eine 08/15-anwendung unmengen an speicher benötigt... aber von freiem speicher alleine hat man schließlich nichts, daher ist der mechanismus an sich ja eigentlich recht gut, für uns wird er jedoch zum stolperstein... mit einer zweiten applikation, die bewusst speicher "frisst", damit der speicher freigegeben wird, hatten wir "teilerfolge"... leider ist das erstens keine besonders schöne lösung und zweitens bekommt man damit auch nicht 100% zurück :(
okay, an dieser stelle könnte man meinen, es wäre ein simples leak... wir verwenden ziemlich viel autopointer, was die leak-suche erschwert, weil die daten ja doch zerstört werden, und wenns erst im destruktor des letzten existierenden objekts passiert... hier haben wir versucht, speicherabbilder zur laufzeit zu bekommen, von verwaisten autopointern keine spur :(
nächster verdacht: speicherfragmentierung. bevor die ganze nachrichten als riesen-strings zusammengestückelt werden, gibts es etliche objekte, wiederum die pointer, enumtypen und sonstigen objekttechnischen kleinkram als container zusammenhalten... gut möglich, dass hier der speicher fragmentiert und eben einfach wo anders nach passenden speicherbereichen gesucht wird... wir hatten sogar einen teilerfolg, der die these belegen könnte...
mit der funktion 'mallopt' aus malloc.h haben wir probehalber M_MMAP_THRESHOLD auf 0 gesetzt, was dann zur folge hatte, dass der komplette speicher unserer anwendung via mmap() allokiert wurde, also rein durch memory pages und nicht am stack... die gute nachricht zuerst: der speicher kam mit fast 100% zurück, wenn "ausgekehrt" wurde... ABER: anscheinend sind unsere objekte so klein, dass einen x-fachen overhead pro allokation hatten, der speicherverbrauch stieg um ein vielfaches an... also nicht praktikabel... :(
unser letzter strohhalm war, eine methode (oder besser gesagt, methoden im sinne von C++) zu finden, die den speicherverbrauch etwas "realistischer" oder praxistauglicher zu berechnen... in der funktion 'mallinfo' von <malloc.h> gibt es einen wert 'fordblks', der angeblich den wert des "halbfreien" speichers in byte ausgab... dann hätten wir uns behelfen können und unseren freien speicher einfach aus <freemem>+<fordblks> berechnen könne, wäre zwar auch nur eine virtuelle größe gewesen, aber eben für unseren zweck realitätsnäher als /proc/meminfo und konsorten... dummerweise kamen wir hier auch nicht auf die erhofften werte... so errechnet war der wert des freien speichers zwar höher, aber immer noch weit weg von dem, was wir uns erwartet hätten...
an dieser stelle muss ich nun sagen, dass ich nicht der absolute linux-experte bin und mir aufgrund dieses problems einiges halbwissen angeeignet habe, welches ich nun hier in die waagschale werfe...
aber ich bin wirklich für jeden hint, link, gedankengang und jede idee dankbar, die hier eingeworfen wird...
gibt es vielleicht noch tools, mit denen man den code dahingehend untersuchen könnte (profiler, leakchecker... z.b. vailgrind, welches uns keine nennenswerten leaks bescheinigt hat)
wie kann man effektiv vermeiden, dass speicherfragmentierung auftritt? bis jetzt hab ich nur in erfahrung gebracht, dass es das beste wäre, eine eigene speicherverwaltung zu schreiben...
gibt es noch andere methoden, den tatsächlichen speicherverbrauch eines prozesses zu berechnen?
kann man das memorymanagement "tunen", ohne einen solchen overkill wie oben beschrieben zu beschwören?
ich erwarte von niemandem, wirklich die gesamte problematik zu erfassen, das tun wir wohl selber auch nicht... aber wenn euch irgendwas bekannt vorkommt und ihr lösungen/erfahrungswerte/tipps dazu habt, postet einfach mal... wir können doch nicht die einzigen sein, die auf nem kleinen gerät mit linux-memory-management probleme haben...
Bei Fragen zu versionen/tools usw. bitte keine falsche scheu, aber ich wollte es vorerst etwas grundsätzlicher halten, es muss ja nicht unbedingt an einer kombination bestimmter komponenten liegen...
viel dank für jeden input!
mfG DoNuT
jo, es ist mein erster post hier, und gleich mit nem ganz dicken problem...
und zwar (soviel kann ich wohl sagen), wir entwickeln software für ein embedded-gerät mit nem arm-prozessor und nicht allzuviel speicher, hier treten aber ein paar probleme auf...
ich versuch mal, das grob zu umreißen...
ein großer teil der funktionalität unserer anwendung ist, von dem gerät (okay, ein RFID-reader) daten zu akquirieren, daraus nen fette xml-textmessage zu machen und diese periodisch an einen beliebigen abnehmer übers netzwerk rauszusenden... ist dieser abnehmer nicht verfügbar, puffern wir die messages bis zu einem bestimmten grad (z.b. 1200 kb freier RAM), darunter hören wir auf, da man nur mehr den stecker am gerät ziehen kann, wenn der speicher volläuft...
verbindet sich der abnehmer, sollten die gepufferten nachrichten eigentlich rausgeblasen werden und würden uns erwarten, dass der speicherverbrauch im großen und ganzen auf das niveau "vor dem sturm" zurückginge, was eben nicht passiert...
es bleibt ein großer batzen hängen - laut /proc/meminfo oder dem gebrauch von sysinfo... wir wissen, dass aufgrund des speichermanagements von linux die sache mit dem "wirklich" freien speicher keine so einfache milchmädchenrechnung ist, weil ungenutzte speicherbereiche noch einem prozess zugeordnet bleiben, solange kein anderer darauf angewiesen ist - deswegen wundert man sich auch oft, warum eine 08/15-anwendung unmengen an speicher benötigt... aber von freiem speicher alleine hat man schließlich nichts, daher ist der mechanismus an sich ja eigentlich recht gut, für uns wird er jedoch zum stolperstein... mit einer zweiten applikation, die bewusst speicher "frisst", damit der speicher freigegeben wird, hatten wir "teilerfolge"... leider ist das erstens keine besonders schöne lösung und zweitens bekommt man damit auch nicht 100% zurück :(
okay, an dieser stelle könnte man meinen, es wäre ein simples leak... wir verwenden ziemlich viel autopointer, was die leak-suche erschwert, weil die daten ja doch zerstört werden, und wenns erst im destruktor des letzten existierenden objekts passiert... hier haben wir versucht, speicherabbilder zur laufzeit zu bekommen, von verwaisten autopointern keine spur :(
nächster verdacht: speicherfragmentierung. bevor die ganze nachrichten als riesen-strings zusammengestückelt werden, gibts es etliche objekte, wiederum die pointer, enumtypen und sonstigen objekttechnischen kleinkram als container zusammenhalten... gut möglich, dass hier der speicher fragmentiert und eben einfach wo anders nach passenden speicherbereichen gesucht wird... wir hatten sogar einen teilerfolg, der die these belegen könnte...
mit der funktion 'mallopt' aus malloc.h haben wir probehalber M_MMAP_THRESHOLD auf 0 gesetzt, was dann zur folge hatte, dass der komplette speicher unserer anwendung via mmap() allokiert wurde, also rein durch memory pages und nicht am stack... die gute nachricht zuerst: der speicher kam mit fast 100% zurück, wenn "ausgekehrt" wurde... ABER: anscheinend sind unsere objekte so klein, dass einen x-fachen overhead pro allokation hatten, der speicherverbrauch stieg um ein vielfaches an... also nicht praktikabel... :(
unser letzter strohhalm war, eine methode (oder besser gesagt, methoden im sinne von C++) zu finden, die den speicherverbrauch etwas "realistischer" oder praxistauglicher zu berechnen... in der funktion 'mallinfo' von <malloc.h> gibt es einen wert 'fordblks', der angeblich den wert des "halbfreien" speichers in byte ausgab... dann hätten wir uns behelfen können und unseren freien speicher einfach aus <freemem>+<fordblks> berechnen könne, wäre zwar auch nur eine virtuelle größe gewesen, aber eben für unseren zweck realitätsnäher als /proc/meminfo und konsorten... dummerweise kamen wir hier auch nicht auf die erhofften werte... so errechnet war der wert des freien speichers zwar höher, aber immer noch weit weg von dem, was wir uns erwartet hätten...
an dieser stelle muss ich nun sagen, dass ich nicht der absolute linux-experte bin und mir aufgrund dieses problems einiges halbwissen angeeignet habe, welches ich nun hier in die waagschale werfe...
aber ich bin wirklich für jeden hint, link, gedankengang und jede idee dankbar, die hier eingeworfen wird...
gibt es vielleicht noch tools, mit denen man den code dahingehend untersuchen könnte (profiler, leakchecker... z.b. vailgrind, welches uns keine nennenswerten leaks bescheinigt hat)
wie kann man effektiv vermeiden, dass speicherfragmentierung auftritt? bis jetzt hab ich nur in erfahrung gebracht, dass es das beste wäre, eine eigene speicherverwaltung zu schreiben...
gibt es noch andere methoden, den tatsächlichen speicherverbrauch eines prozesses zu berechnen?
kann man das memorymanagement "tunen", ohne einen solchen overkill wie oben beschrieben zu beschwören?
ich erwarte von niemandem, wirklich die gesamte problematik zu erfassen, das tun wir wohl selber auch nicht... aber wenn euch irgendwas bekannt vorkommt und ihr lösungen/erfahrungswerte/tipps dazu habt, postet einfach mal... wir können doch nicht die einzigen sein, die auf nem kleinen gerät mit linux-memory-management probleme haben...
Bei Fragen zu versionen/tools usw. bitte keine falsche scheu, aber ich wollte es vorerst etwas grundsätzlicher halten, es muss ja nicht unbedingt an einer kombination bestimmter komponenten liegen...
viel dank für jeden input!
mfG DoNuT