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

Following up on a previous posting (Uncollected garbage leads to swapping ...) I have (finally) isolated the cause of my leaking memory :) A code snippet illustrating the problem is posted below. Running this progam in one window while "watching" vmstat in another window should make the problem pretty clear (the "sleep" is included just to prevent the sample from locking up anybody else's computer :) My configuration is: Perl 5.8.0 as supplied with RedHat 9 running in 512MB

If I have overlooked something, PLEASE berate/enlighten me ! Otherwise, I have not seen any reports of this problem and would appreciate it is someone could post a trouble report in the appropriate place. Thanks !
#!/usr/bin/perl use strict; use warnings; use List::Util qw(reduce); sub reducer { my @d = (6,7,8,9); my $m = reduce {$d[$b] < $d[$a] ? $b : $a} 0..3; # find smallest } for (;;) { for (my $i=0; $i<10000; $i++) { reducer(); } sleep(1); }

Replies are listed 'Best First'.
Re: Uncollected Garbage ...
by Corion (Patriarch) on Feb 26, 2004 at 22:58 UTC

    The bug reports on CPAN for List::Util don't list it, but I looked at the source code, and found the following C code for reduce:

    void reduce(block,...) SV * block PROTOTYPE: &@ CODE: { SV *ret = sv_newmortal(); int index; GV *agv,*bgv,*gv; HV *stash; CV *cv; OP *reducecop; PERL_CONTEXT *cx; SV** newsp; I32 gimme = G_SCALAR; U8 hasargs = 0; bool oldcatch = CATCH_GET; if(items <= 1) { XSRETURN_UNDEF; } agv = gv_fetchpv("a", TRUE, SVt_PV); bgv = gv_fetchpv("b", TRUE, SVt_PV); SAVESPTR(GvSV(agv)); SAVESPTR(GvSV(bgv)); GvSV(agv) = ret; cv = sv_2cv(block, &stash, &gv, 0); reducecop = CvSTART(cv); SAVESPTR(CvROOT(cv)->op_ppaddr); CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL]; #ifdef PAD_SET_CUR PAD_SET_CUR(CvPADLIST(cv),1); #else SAVESPTR(PL_curpad); PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]); #endif SAVETMPS; SAVESPTR(PL_op); SvSetSV(ret, ST(1)); CATCH_SET(TRUE); PUSHBLOCK(cx, CXt_SUB, SP); PUSHSUB(cx); if (!CvDEPTH(cv)) (void)SvREFCNT_inc(cv); for(index = 2 ; index < items ; index++) { GvSV(bgv) = ST(index); PL_op = reducecop; CALLRUNOPS(aTHX); SvSetSV(ret, *PL_stack_sp); } ST(0) = ret; POPBLOCK(cx,PL_curpm); CATCH_SET(oldcatch); XSRETURN(1); }

    Now the problem is that I may know how to read C, but I sure don't know XS. My wild guess is that the

    if (!CvDEPTH(cv)) (void)SvREFCNT_inc(cv);
    should be matched with a decrement (most likely SvREFCNT_dec) to prevent memory leaking. But quite possibly, the problem might lie elsewhere in the XS code. I think that you best report the bug to the author via RT, and include your test snippet or a link to this thread.

      I wonder if the guy who wrote it knows how to read C (or XS) cause that code sure is hard to follow
Re: Uncollected Garbage ...
by kvale (Monsignor) on Feb 26, 2004 at 22:57 UTC
    The program
    #!/usr/bin/perl use strict; use warnings; use List::Util qw(min); sub reducer { my @d = (5,6,7,8); my $m = min @d; } for (;;) { for (my $i=0; $i<10000; $i++) { reducer(); } sleep(1); }
    seems rock-steady on memory consumption, so perhaps there is something awry with the reduce function. This is with perl 5.8.0, Mandrake 9.1.

    Update: Yeah, I'm not calulating the same thing, just narrowing the possibilities.

    -Mark

Re: Uncollected Garbage ...
by Anonymous Monk on Feb 26, 2004 at 23:06 UTC
    If I have overlooked something, PLEASE berate/enlighten me !
    What version of List::Util do you have? (your report your perl version, but that is half the picture).
      Anonymous Monk,
      You could walk your @INC paths and find the location of the Util.pm and peek inside. I find the following method to be easier:
      $ perl -M"List::Util 7.0" List::Util version 7 required--this is only version 1.13. BEGIN failed--compilation aborted. $
      Cheers - L~R
      I am using the version of List::Util that is supplied with Perl 5.8.0. How do I determine the version of List::Util ?

      A bug report has been filed as suggested by one of the previous responders. Thanks for the help !