Schrift
[thread]9035[/thread]

Memory Leak



<< >> 10 Einträge, 1 Seite
weismat
 2007-05-25 14:39
#76921 #76921
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Welche Strategie benutzt Ihr, Memory Leaks zu finden?
Ich habe in einem recht einfachen Skript einen Leak und habe keine gute Idee, wo ich suchen muss.
Das Skript arbeitet mit einer großen Schleife, die einmal pro Minute durchlaufen wird und verliert pro Durchlauf ein 10 MB.
Wie kann ich erzwingen, daß ein Hash-Table gelöscht? Den habe ich im Verdacht, aber das Umstellen der Deklaration von außerhalb nach innerhalb der Schleife, hat nix gebracht...
pq
 2007-05-25 15:12
#76922 #76922
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
- strict benutzen
- CPAN:Devel::Size für einzelne datenstrukturen benutzen
- innerhalb er schleife debuggen, also an mehreren stellen die prozessgrösse
  beobachten / mitloggen
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
weismat
 2007-05-25 18:03
#76923 #76923
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Hmm...Gute Ideen...
strict benutze ich schon immer...
Ich habe alle Variablen lokal gemacht - ergo würde ich erwarten, daß die Garbage Collection automatisch die Variablen wegräumt, wenn ich das nächste mal durch meine while Schleife durchlaufe.
Was mich überracht, ist der Sprung in 4 MB Schritten.
Sucher
 2007-05-25 19:50
#76924 #76924
User since
2007-03-26
47 Artikel
BenutzerIn
[default_avatar]
Hallo,

CPAN:Devel::Leak

kann auch nützlich sein.

Grüße,
bloonix
 2007-05-25 21:44
#76925 #76925
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Wenn du hier und da schauen möchtest, was dein Skript aktuell so macht...

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use strict;
use warnings;
use Sys::Statistics::Linux;
use Data::Dumper;

my $pid = $$;

my $lxs = Sys::Statistics::Linux->new(
  Processes => {
     init => 1,
     pids => [ $pid ]
  }
);

sleep 1;

my $stat = $lxs->get->{Processes}->{$pid};
print Dumper($stat);


---
Edit: vorausgesetzt du nutzt ein Linux\n\n

<!--EDIT|opi|1180177349-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
betterworld
 2007-05-26 17:19
#76926 #76926
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
weismat: Benutzt Du zyklische Referenzen?\n\n

<!--EDIT|betterworld|1180187135-->
weismat
 2007-05-26 19:05
#76927 #76927
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Betterworld hat wohl den Nagel auf dem Kopf getroffen.
Ich benutze sehr viele tiefgeschachtelte Referenzen auf Hashes, die mehrere Ebenen tief sind.
Ich parse große Datenstrukturen und habe auch schon den Parser ausgetauscht, weil ich dort zuerst das Leak vermutet hatte. Der eine Parser ist selbst geschrieben, der andere basiert auf JSON::XS.
Wie sollte ich solche Datenstrukturen aufräumen, wenn es der Garbage Collector nicht schafft? Ich hätte erwartet, daß durch ein einfaches Zuweisen nach einem neuen Parsing alles darunter weggeräumt wird.
Das Programm läuft übrigens unter Solaris...Zum Glück hat die Maschine noch so 10 GB Swap frei - aber ich war erschrocken, als ich den Speicherbedarf zufällig gesehen habe.\n\n

<!--EDIT|weismat|1180192504-->
weismat
 2007-05-26 20:08
#76928 #76928
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Dieser Artikel sieht ganz gut aus...
http://letsgetdugg.com/view....95;Perl
betterworld
 2007-05-26 20:56
#76929 #76929
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
[quote=weismat,26.05.2007, 17:05]Betterworld hat wohl den Nagel auf dem Kopf getroffen.
Ich benutze sehr viele tiefgeschachtelte Referenzen auf Hashes, die mehrere Ebenen tief sind.[/quote]
Tief und verschachtelt ist kein Problem, sondern zyklisch.  Das bedeutet praktisch, dass irgendwo in einer Struktur eine Referenz auf den Anfang der Struktur gespeichert ist, wie in den folgenden Beispielen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
# Einfacher Hash
my $foo; $foo = {foo=>\$foo};

# Komplizierterer Hash
my $bar = {
   blubb => {}
};
$bar->{blubb}{ding}{dang} = \$bar->{blubb};

# Closure (besonders trickreich)
my ($sub1, $sub2);
$sub1 = sub {sub2->();};
$sub2 = sub {sub1->();};


Wenn Du an einem bestimmten Punkt weisst, dass Du eine Struktur nicht mehr brauchst, kannst Du versuchen, den Kreis zu brechen, damit der Garbage Collector den Rest machen kann.  (Das ist bei Closures allerdings oft nicht moeglich.)
Ansonsten hilft weaken() aus Scalar::Util.  Wenn man das verwendet, sollte man aber gut testen, ob es wirklich funktioniert, denn meiner Erfahrung nach verhaelt es sich manchmal seltsam.
Eine dritte Moeglichkeit, von der ich mal gelesen habe, sind Proxy-Objekte.  Das ist allerdings ziemlich obskur und ich habe es auch noch nie eingesetzt.

DESTROY ist hier uebrigens zum Debuggen hilfreich.\n\n

<!--EDIT|betterworld|1180198605-->
weismat
 2007-05-29 14:30
#76930 #76930
User since
2003-08-18
142 Artikel
BenutzerIn
[default_avatar]
Vielen Dank für die Hilfe.
Das Loch kam durch einen mehrdimensionalen Hash Table zustande, der auf Zweige eines Baumes verweisst.
Über diesen mehrdimensionalen Hash-Table wird der Baum nach mehreren Kriterien sortiert.
Der Baum lief dann zwar out-of-scope, aber die Zweige wurden nicht gelöscht, wenn der Hash-Table out-of-scope ging.
Ich habe erstmal den Hash-Table persistent gemacht, indem ich noch einen zwei Keys hinzugefügt habe und damit ist das Speicher-Loch verschwunden.
<< >> 10 Einträge, 1 Seite



View all threads created 2007-05-25 14:39.