Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Simple Program Huge Problem

by crusher (Acolyte)
on Nov 05, 2008 at 22:45 UTC ( [id://721851]=perlquestion: print w/replies, xml ) Need Help??

crusher has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I’m experiencing a strange behavior while executing this script (that I made especially to help me track what appears to be a memory leak):

#!/usr/bin/perl -w use strict; use Tree::Simple; my $CR="\n"; my @array = qw/ 112.75 850.22 100.65 1651.82 21.82 1598.36 962.97 15.1 +0 85.55 112.75 850.22 21.82 1651.82 1598.36 962.97 /; for (my $j=0;$j<10**10;$j++) { #always the same code to execute my $i=0; my $tree = Tree::Simple->new("root tree",Tree::Simple->ROOT); printleaf(\$tree); $tree->addChild(Tree::Simple->new("$array[$i]")); printleaf(\$tree->getChild(0)); my @_auxarray=@array; splice(@_auxarray,$i,1); foreach my $elem (@_auxarray) { printleaf(\Tree::Simple->new("$elem",$tree->getChild(0))); } undef @_auxarray; $tree->DESTROY(); #clear circular references $tree->traverse(sub { my($_tree)=@_; print (("\t" x $_tree->getDepth()), $_tree->ge +tNodeValue(),"\n"); }); undef $tree; } my $pause=<STDIN>; #variable only used to pause the program sub printleaf{ my ($_leaf)=$_[0]; print("VALUE: ",$$_leaf->getNodeValue()," | ROOT?: ",$$_leaf->isRo +ot() ? "true" : "false"," | DEPTH: ",$$_leaf->getDepth()," | INDEX: " +,$$_leaf->getIndex(),"$CR"); }

Every time that the loop repeats, the memory usage increases even if I undef the reference to the object.

For what I know if an object loses all its references the “perl garbage collector” should automatically destroy it and free the memory, right?

Could someone help me and tell me if I’m making any mistake?


I’m using ActivePerl 5.10 B1004 and the module Tree::Simple version 1.18.

Replies are listed 'Best First'.
Re: Simple Program Huge Problem
by almut (Canon) on Nov 05, 2008 at 23:44 UTC

    It seems the DESTROY method doesn't quite work as advertised in this case (i.e. it doesn't destroy all circular references). If you use Data::Dumper; and write

    print Dumper $tree; $tree->DESTROY(); #clear circular references print Dumper $tree; <STDIN>;

    you can compare the dump before and after the DESTROY call. You'll notice that the _parent attribute of the first-level child nodes has been set to undef, but not those of the children further down in the tree...

    Anyway, as the module also allows for weak references to be used, you could also simply write

    use Tree::Simple 'use_weak_refs';

    ...and be happy :) — Just tried it, no memory leaks any longer.

      I really appreciated your answer,
      Thank you very much!!

      Although the memory usage still increases it’s nothing compared with the situation before “use_weak_refs”. I’ll try to investigate further with the method that you showed.

        I usually avoid posting Perl-free nodes like this one... but in this case, I'd just like to say a quick thanks in reverse.  It's always a pleasure to have self-contained code that I can just cut-n-paste and run. That makes me far more inclined to try to replicate the problem and look for a solution... — Thanks, and good luck with finding the remaining leaks!

Re: Simple Program Huge Problem
by Krambambuli (Curate) on Nov 06, 2008 at 11:01 UTC
    Not so long ago, I've got a hint about using valgrind for that kind of investigation. If you don't know this great tool already, you might want to check it out.


    Krambambuli
    ---
Re: Simple Program Huge Problem
by crusher (Acolyte) on Nov 08, 2008 at 18:54 UTC
    Like ‘almut’ said the DESTROY method doesn’t work as expected so I begin to write a subroutine in the hope of finding a solution to the memory leak problem…
    I think I’m almost there however after tracing the execution with ‘Devel::Trace’ I found that the execution order is STEP1; STEP2 and then STEP4, and should be STEP1;STEP2;STEP3.

    If the program reached the last return statement why is it going to STEP4 and not to the main function? Could anyone tell me what is going out?

    #!/usr/bin/perl -w use strict; use Tree::Simple; #use Tree::Simple 'use_weak_refs'; use Data::Dumper; #use Devel::Trace; $Data::Dumper::Indent=1; #$Devel::Trace::TRACE=0; local $|=1; my $CR="\n"; my $WS="-------------------------------------------------------------- +---$CR"; my @array = qw/ 112.75 850.22 100.65 /; #for (my $j=0;$j<1;$j++) # { #always the same code to execute my $i=0; my $tree = Tree::Simple->new("root tree",Tree::Simple->ROOT); printleaf(\$tree); $tree->addChild(Tree::Simple->new("$array[$i]")); printleaf(\$tree->getChild(0)); my @_auxarray=@array; splice(@_auxarray,$i,1); foreach my $elem (@_auxarray) { printleaf(\Tree::Simple->new("$elem",$tree->getChild(0))); } undef @_auxarray; print "${WS}DATA DUMPER: $CR"; print Dumper $tree; print "${WS}"; FULLY_DESTROY($tree); ###########################STEP 3############################ print "${WS}DATA DUMPER: $CR"; print Dumper $tree; #$tree->traverse(sub { my($_tree)=@_; #print (("\t" x $_tree->getDepth()), $_tree->g +etNodeValue(),"\n"); #}); undef $tree; # } <STDIN>; #pause sub printleaf{ my ($_leaf)=$_[0]; print("VALUE: ",$$_leaf->getNodeValue()," | ROOT?: ",$$_leaf->isRo +ot() ? "true" : "false"," | DEPTH: ",$$_leaf->getDepth()," | INDEX: " +,$$_leaf->getIndex(),"$CR"); } sub FULLY_DESTROY{ my ($self)=$_[0]; print ($self->getNodeValue()," "); while(1) { ###########################STEP 4############################ if(!ref($self->{_parent}) && $self->{_parent} eq 'root' && sca +lar(@{$self->{_children}})==0) { $self->{_parent} = undef; print ("called last to end the sub routine$CR"); ###########################STEP 1######################### +### last; } if(defined($self->{_children}) && $self->getChildCount!=0) { print ("childs ",$self->getChildCount(),"$CR"); FULLY_DESTROY($self->getAllChildren()); } #if has no childs saves the father reference my $ref; my $index=$self->getIndex(); print("index ",$index," "); if(($index+1) == ($self->getParent()->getChildCount())) #last +in the branch { print ("childs 0 last in branch$CR"); $ref = \$self->getParent(); $self->{_parent} = undef; @{$$ref->{_children}}=(); FULLY_DESTROY($$ref); } else { print ("childs 0 not last in branch$CR"); $ref = \$self->getSibling($index+1); $self->{_parent} = undef; FULLY_DESTROY($$ref); } } ###########################STEP 2############################ print "end should return to main function$CR$CR"; return; }
      a call to return after each recursive call, like:
      FULLY_DESTROY($$ref); return;
      solves the problem don't ask me why but it works...

        You seem to be confused about your program flow. From looking at the call structure of your program, the flow will be

        1. Step 1
        2. Step 2
        3. Step 4
        4. Step 3

        You have an endless loop in FULLY_DESTROY, which I don't see where you leave it. Maybe that is the reason for why your program does work differently than you expect it to. You would have found this by removing all other things from your program and replacing it by simple statements that just printed out "STEP 1" etc.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://721851]
Approved by Old_Gray_Bear
Front-paged by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-24 02:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found