On Fri, 7 Sep 2001, Alex Krohn wrote:

> Hi,
>
> > >> With this simple test script:
> > >>
> > >> print "Content-type: text/html\n\n";
> > >> my $var = 'x' x 500000;
> > >
> > > our $var = 'x' x 500000;
> > >
> > >>
> > >> my $sub = sub { my $sub2 = sub { $var; }; };
> > >> print "Done\n";
> > >>
> > >> $var does not get freed, and the process grows each request. Has anyone
> > >> seen this sort of behavior and have any ideas/workarounds (besides don't
> > >
> > > yes.  this is the documented behavior for closures.  the anonymous sub
> > > must have it's own copy of $var which happens to be 500k plus perl
> > > overhead on each invocation.
> >
> > I think the problem is that $var doesn't get freed even when $var and
> > $sub and $sub2 have all gone out of scope.  That's a perl bug for which I
> > can fathom no workaround.
> >
> > If any of those variables are still in scope, then of course $var can't
> > get freed.
>
> Yes, upon further investigation, this perl script:
>
> while (1) {
>       {
>               my $var = 'x' x 500000;
>               my $sub = sub { my $sub2 = sub { $var; } };
>       }
>       # $var and $sub should be gone, but memory is never freed
>       sleep 1; # Don't crash things =)
> }
>
> will grow forever as $var never seems to be freed even when everything
> should go out of scope, definately a perl bug, not a mod_perl one. =)

Look like memory leaking to me. The reference count is done incorrectly,
which leads to memory leaking:

use GTop;
use Devel::Peek;
my $gtop = GTop->new;

for (1..3) {
    my $a = 'x' x 500000;
    {
        sub { $a; };
    }
    printf "RERCNT %s: \$a=%d\n",
        GTop::size_string($gtop->proc_mem($$)->rss),
        Devel::Peek::SvREFCNT($a);
}

prints:

RERCNT  3.5M: $a=1
RERCNT  3.5M: $a=1
RERCNT  3.5M: $a=1

all fine!

use GTop;
use Devel::Peek;
my $gtop = GTop->new;

for (1..3) {
    my $a = 'x' x 500000;
    {
        sub { my $sub2 = sub { $a; }; };
    }
    printf "RERCNT %s: \$a=%d\n",
        GTop::size_string($gtop->proc_mem($$)->rss),
        Devel::Peek::SvREFCNT($a);
}

prints:

RERCNT  3.5M: $a=4
RERCNT  4.0M: $a=3
RERCNT  4.5M: $a=3

1. the reference counting is wrong
2. memory leaks (because of 1)

This is a hack to fix the leaking (well, almost):

use GTop;
use Devel::Peek;
my $gtop = GTop->new;

for (1..3) {
    my $a = 'x' x 500000;
    {
        sub { my $sub2 = sub { $a; }; };
        Devel::Peek::SvREFCNT_dec($a);
        Devel::Peek::SvREFCNT_dec($a);
    }
    printf "RERCNT %s: \$a=%d\n",
        GTop::size_string($gtop->proc_mem($$)->rss),
        Devel::Peek::SvREFCNT($a);
}

prints:

RERCNT  3.5M: $a=2
RERCNT  4.0M: $a=1
RERCNT  4.0M: $a=1


> Oddly, if you just do
>
>       my $sub = sub { $var; };
>
> it does not grow, definately something strange going on. Happens on
> perl 5.004_04, 5.005_03 and 5.6.1.

You mean this works for you?:

while (1) {
       {
               my $var = 'x' x 500000;
               my $sub = sub { $var; };
       }
       # $var and $sub should be gone, but memory is never freed
       sleep 1; # Don't crash things =)
}

that's because your $sub goes out of scope. the other one seems like a
bug.

If I didn't miss something, it seems that we need to run this through p5p.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide
mailto:[EMAIL PROTECTED]   http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/




Reply via email to