On 31 Aug 2000 [EMAIL PROTECTED] wrote:

> Doug,
> 
> Sorry to belabor a dull issue, but I'm not sure I'm getting my point across.

no problem, this is important stuff to understand.
 
> Most of the troubles I've run across in the mod_perl and libapreq code
> have to do with attempts to allocate memory resources for buffers 
> at runtime.  That's exactly what the BUFF API does, right?

not really, BUFF uses some stack allocation, it's generally up to the
caller to manage i/o buffers.
 
> What I'm seeing is that you are also resizing/reallocating these buffers
> each time the code is called. For instance, the original 
> get_client_block had this line in it:
> 
> > -    buffer = (char*)palloc(r->pool, bufsiz);
> 
> The one you just sent me has this line instead:
> 
> > +    SvGROW(buffer, bufsiz+1);
> 
> I'm not sure what SvGROW does, but if it involves a malloc
> without freeing the old buffer, you've got the same problem as before.  
> Each time the perl version of get_client_block is called, 
> SvGROW will work it's majic on RAM, and perl won't give that RAM
> back to the OS. 

but that "problem" still existed with your patch in this line:
        sv_setpvn((SV*)ST(1), buffer, nrd);

same thing happens underneath (see sv.c).  we can't just point Perl
variables at buffers allocated on the stack.  SvGROW() will only malloc()
(or realloc) if the buffer isn't already large enough to the given length.
Perl hangs onto that allocation as an optimization, so it only has to
malloc() once for a given variable, and maybe realloc() if a later string
assignment is larger.  consider this example:

sub foo {
   ...
    my $buff;
    while (my $len = $r->get_client_block($buff, 1024)) {
        print "$buff\n";
    }
   ...
}

the SvGROW() underneath will only trigger malloc() for $buff _once_, for
the entire lifetime of the process.
Perl will only release the string buffer allocation if you explicity
undef() the variable.  this is true for all variables, including those
scoped with my().  clearly, you would not want to undef($buff) inside the
while loop, otherwise malloc() will be called each time through the loop.
outside the loop would not be so bad, then malloc() will only happen for
$buff each time sub foo is called.  if it's called often, like for every
request, it might be better to let Perl hang onto the allocation, that's
up to you.

now, what happens when that buffer is released depends on your Perl and
perhaps os.  if your Perl is built with Perl's malloc, the free()
triggered by undef() will give the memory back to Perl's pool of memory.
otherwise, free() will probably resolve to libc's free().  on some
platforms that means it is "given back to the os", on others it just means
that chunk of memory is available for reuse in that process the next time
somebody malloc's.

Reply via email to