Speicherbelegung verstehen
am 19.07.2007 11:52:10 von unknownPost removed (X-No-Archive: yes)
Post removed (X-No-Archive: yes)
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig92502F9ACDE186AC541EE80A
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Hallo,
Martin Trautmann wrote:
> gibt's irgendwelche Optionen, wie ich mir irgendwie anzeigen lassen
> kann, fuer welche Variablen oder sonstige Aktivitäten perl wie viel
> Speicher verbraucht?
Devel::Size
HTH,
Moritz
--=20
Moritz Lenz
http://perl-6.de/ http://moritz.faui2k3.org/
--------------enig92502F9ACDE186AC541EE80A
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFGnzXDAAkekJBI0yIRAmFXAKDTv2lXrIILSMrbM4EMUCQo2ZCp9ACf cC9i
/7y0wSGBUZfMoTU6JjzpGvw=
=g65A
-----END PGP SIGNATURE-----
--------------enig92502F9ACDE186AC541EE80A--
Martin Trautmann
> Hallo,
>
> gibt's irgendwelche Optionen, wie ich mir irgendwie anzeigen lassen
> kann, fuer welche Variablen oder sonstige Aktivitäten perl wie viel
> Speicher verbraucht?
>
>
> Ich habe hier ein Script, das WWW::Mechanize verwendet. Dabei wird die
> ein ganzes Array an URLs abgearbeitet. Wenn der Seitenabruf
> fehlschlaegt, dann dekrementiere ich den Zaehler, breche die Routine mit
> "return" ab und wiederhole den Aufruf der Routine nochmals mit dem
> vorangegangenen URL:
>
> while ($ii < $i) {
> call_url ($url[$ii++]);
> }
>
> sub call_url {
> my ($url)=@_;
> $m->get($url)
> if !($m->success) {
> $ii--;
> return;}
> # otherwise do some processing on the results and write them to a file
> }
>
>
>
>
> Ich verwende perl -w und use strict. Alle open/close auf die Files
> fuehre ich wohl aus. Irgendwelche globalen Variablen werden immer wieder
> zurueckgesetzt - da sollte sich nichts endlos aufsummieren.
>
> Wenn ich den Speicherverbrauch beobachte, dann waechst der ins
> unermessliche. Ich starte mit einer Initalisierung des URL-Arrays mit
> etwa 1000 Werten. Damit braucht das Script am Anfang etwa 10 MB.
>
> Das ganze laeuft dann und hat nach 500 Abfragen schon einen
> Speicherverbrauch von etwa 500 MB. Nun wuesste ich gerne, was hier alles
> belegt wird - oder wie ich dieses Ausufern verhindern kann.
Zum Beobachten von Memory-Leaks finde ich das CPAN-Modul Devel::Leak
sehr nützlich.
Gruß,
Slaven
--
Slaven Rezic - slaven
BBBike - route planner for cyclists in Berlin
WWW version: http://www.bbbike.de
Perl/Tk version for Unix and Windows: http://bbbike.sourceforge.net
Post removed (X-No-Archive: yes)
Post removed (X-No-Archive: yes)
Martin Trautmann wrote:
> Ich habe hier ein Script, das WWW::Mechanize verwendet. Dabei wird die
> ein ganzes Array an URLs abgearbeitet. Wenn der Seitenabruf
> fehlschlaegt, dann dekrementiere ich den Zaehler, breche die Routine mit
> "return" ab und wiederhole den Aufruf der Routine nochmals mit dem
> vorangegangenen URL:
>
> while ($ii < $i) {
> call_url ($url[$ii++]);
> }
>
> sub call_url {
> my ($url)=@_;
> $m->get($url)
> if !($m->success) {
> $ii--;
> return;}
> # otherwise do some processing on the results and write them to a file
> }
Nebenbei: Das ist schlechter Code, da die Subroutine
globale Variable nutzt.
> Ich verwende perl -w und use strict. Alle open/close auf die Files
> fuehre ich wohl aus. Irgendwelche globalen Variablen werden immer wieder
> zurueckgesetzt - da sollte sich nichts endlos aufsummieren.
>
> Wenn ich den Speicherverbrauch beobachte, dann waechst der ins
> unermessliche. Ich starte mit einer Initalisierung des URL-Arrays mit
> etwa 1000 Werten. Damit braucht das Script am Anfang etwa 10 MB.
>
> Das ganze laeuft dann und hat nach 500 Abfragen schon einen
> Speicherverbrauch von etwa 500 MB. Nun wuesste ich gerne, was hier alles
> belegt wird - oder wie ich dieses Ausufern verhindern kann.
Es ist wohl anzunehmen, dass WWW::Mechanize den Speicher verbraucht.
Kann es sein, dass das/die WWW::Mechanize-Objekte nicht
destrukturiert werden?
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Post removed (X-No-Archive: yes)
Martin Trautmann:
> Ich habe hier ein Script, das WWW::Mechanize verwendet.
Ich an deiner Stelle würde zuerstmal versuchen herauszufinden,
ob WWW::Mechanize der Schuldige ist, indem du dessen
Aufrufe durch "Dummy-Funktionen" ersetzt. Oder du rufst
WWW::Mechanize nur fünfzigmal auf und schaust dir dann den
Speicherbedarf deines Skripts an.
In Perl ist es nichts Ungewöhnliches, dass der Speicher steigt,
während das Skript läuft, da der Interpreter aus Performance-
gründen allokierten Speicher nicht mehr ans Betriebssystem
zurückgibt (was manchmal in persistenten Umgebungen Probleme
macht).
Was mir auch einfällt: wenn du mit Arrays oder Hashes arbeitest,
bei der Übergabe an oder beim Zurückgeben von Funktionen
über Referenzen an. Dadurch müssen sie (die Arrays/Hashes)
nicht kopiert werden. Das spart Speicher und erhöht die
Performance.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Post removed (X-No-Archive: yes)
Martin Trautmann:
> Naja - ohne Mechanize ergibt das Script wenig Sinn.
Es geht ja nur ums Testen (nach dem Ausschlussverfahren):
-> Braucht dein Code ohne Mechanize ebenfalls soviel Speicher,
hat's damit etwas.
-> Ansonsten liegt der Hund in Mechanize oder dessen Umgang
begraben.
Je nach dem Ergebnis des Tests musst du in zwei unterschiedlichen
Ecken weitersuchen.
> > In Perl ist es nichts Ungewöhnliches, dass der Speicher steigt,
> > während das Skript läuft, da der Interpreter aus Performance-
> > gründen allokierten Speicher nicht mehr ans Betriebssystem
> > zurückgibt (was manchmal in persistenten Umgebungen Probleme
> > macht).
>
> Damit haette ich kein Problem, wenn er's dem OS nicht mehr gibt. Aber
> anscheinend nutzt auch das Programm selbst nicht mehr die eigenen,
> eigentlich freigewordenen Bereiche.
Naja, es könnte auch ein Memory Leak sein, obwohl die heutzutage
schon ziemlich selten sind. Welche Perl-Version verwendest du?
Hast du schon, wie von Slaven vorgeschlagen, Devel::Leak ausprobiert?
Auf die schnelle fällt mir auch noch B::LexInfo ein - damit kann sich
recht schön den Platzbedarf in Scratchpads (das sind die Datenstrukturen,
in denen lexikalischen - mit "my" deklarierte - Variable abgelegt werden)
ansehen kann. Und natürlich auch Devel::Peek.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Martin Trautmann
> On 20 Jul 2007 06:12:55 GMT, Martin Trautmann wrote:
> > On 19 Jul 2007 23:50:39 +0200, Slaven Rezic wrote:
> > > Zum Beobachten von Memory-Leaks finde ich das CPAN-Modul Devel::Leak
> > > sehr nützlich.
> >
> > Ah, danke, das werde ich gerne mal ausprobieren - die globalen Variablen waren's
> > anscheinend nicht, die bleiben alle harmlos klein.
>
> Nun bekomme ich hunderte von Meldungen wie
> new 0x18ebd08 :
>
> Anscheinend wurde also wirklich massenhaft irgendwo Speicher verbraten -
> aber womit?
Wenn es zu jedem "new" ein "old" gibt, ist das nicht weiter schlimm.
Du solltest die Anzahl der SV (wird von den Funktionen zurückgegeben)
vorher und nachher vergleichen. Bei einer Schleife solltest du auch
nicht den ersten Lauf testen (weil beim ersten Mal unter Umständen
Code dynamisch nachgeladen wird etc.).
In den Tk-Tests mache ich das ungefähr so:
# Tests for leaking Tk_GetUid (e.g. canvas items)
#### Der erste Aufruf ist nur dazu da, um Tk/Canvas.pm zu laden und
#### wenigstens einmal die zu testenden Methoden aufgerufen zu haben:
my $c = $mw->Canvas->pack;
$c->delete($c->createLine(10,10,100,100, -tags => "a"));
#### Anzahl der SV vorher
$c1 = Devel::Leak::NoteSV($handle);
for(1..1000) {
$c->createLine(10,10,100,100,-tags => "a");
$c->delete("a");
}
#### Anzahl der SV danach
$c2 = Devel::Leak::NoteSV($handle);
#### Ich bin tolerant und erlaube einen Leak von 10 SVs; es ist
#### schwierig, Tk komplett leakfrei zu bekommen...
cmp_ok(($c2-$c1), "<", 10, "Leaking Tk_GetUid, e.g. canvas items");
Gruß,
Slaven
--
Slaven Rezic - slaven
tknotes - A knotes clone, written in Perl/Tk.
http://ptktools.sourceforge.net/#tknotes
Post removed (X-No-Archive: yes)
Post removed (X-No-Archive: yes)
Martin Trautmann wrote:
> On Fri, 20 Jul 2007 13:04:40 +0200, Frank Seitz wrote:
>>
>> Nebenbei: Das ist schlechter Code, da die Subroutine
>> globale Variable nutzt.
>
> Ist das eher ein echtes Problem oder ein Schoenheitsproblem, dass ich
> hier statt Ravioli-Code eher Spaghetti-Code habe?
Ich sehe darin ein echtes Problem, denn solcher Code
wird schnell unwartbar.
> Es erscheint mir eben viel einfacher, das mit globalen Variablen zu
> machen. Ja, im konkreten Fall wird nur eine Variable uebergeben - da
> koennte ich auch mit sinnvollen Return-Werten arbeiten, ob die Schleife
> nochmals erfolgen soll oder nicht. In einer anderen Anwendung habe ich
> aber mehrere Arrays, wo ich's ebenso mache:
>
> my $i =0; # index full counter
> my $ii =0; # index work counter
> my @array1; # one array
> my @array2; # another array
> #... more arrays
>
> fill_arrays(); # fill array 1 and 2, increases $i from 0 to end
> while ($ii<$i) {
> process_line(); # works on $array*[$ii] and may use $ii--
> }
>
> Was gewinne ich, wenn ich es mit lokalen Variablen aufrufen wuerde,
> process_line ($array1[$ii],$array2[$ii],$array3...)
Du gewinnst Klarheit, dadurch dass Deine Funktionen eine
(sichtbare) Schnittstelle haben.
> Ist es sinnvoll, das fill_arrays dann auch so zu bauen, dass es mir die
> dort lokalen arrays erst wieder in de globalen uebergibt, nur um sie
> dann wieder lokal zu verarbeiten?
Ja, das ist sinnvoll. Bei Arrays oder Hashes bietet es sich an,
mit Referenzen zu arbeiten.
> Ich habe den Eindruck, dass der
> globale Ansatz weit leichter verstaendlich ist.
Aber nur so lange Du aus dem Kopf weißt, was die Funktionen
tun und womit sie es tun.
> Ich lerne hier gerne was dazu - aber im Moment ist mein coding style so,
> dass ich global belasse, was mir dort als universell erforderlich
> erscheint und dass ich lokal all das dort verwende, was mit Abschluss der
> Aufgabe wieder ueberfluessig geworden ist.
Das ist Murks. Das wird Dir jeder erfahrene Programmierer sagen.
>> Es ist wohl anzunehmen, dass WWW::Mechanize den Speicher verbraucht.
>> Kann es sein, dass das/die WWW::Mechanize-Objekte nicht
>> destrukturiert werden?
>
> Kann sein - was heisst das?
Dass Dein Programm noch Referenzen auf die WWW::Mechanize-Objekte hält.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Post removed (X-No-Archive: yes)