On Thu, 2006-06-22 at 11:20 -0700, Jay Buffington wrote:
I'm considering writing a PerlLogHandler that will print out the
memory usage (using GTop) before and after each request so I can find
the offending code path.

I wrote this script and it turned out to work very well.  It's small,
so I included it below inline.  It outputs lines that look like this:

[Fri Jun 23 15:29:00 2006] [error] [24962] url: /hogmem before:
154.85M; after: 490.82M; delta: 335.96M

After the weekend I'll look at packaging this up and putting it in
CPAN.  The GTop and Number::Format CPAN modules are preqs.

--------------------------------------------

# The Apache::LogMemoryUsage module is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.

package Apache::LogMemoryUsage;

use strict;
use warnings;

use GTop;
use Apache::Constants qw(OK);
use Number::Format qw(format_bytes);

# deltas lower than this threshold will not be logged
# this is in bytes
my $THRESHOLD = (1024 * 1024) * 4; # 4mb

my $gtop = GTop->new();

# should be called like this in your httpd.conf:
# PerlModule Apache::LogMemoryUsage
# PerlInitHandler Apache::LogMemoryUsage
sub handler {
       my $r = shift;

       $r->pnotes("mem_usage_before_request", $gtop->proc_mem($$)->size());

       # after the request is complete, we'll call the log_handler
       $r->push_handlers( PerlLogHandler => \&log_handler );

       return OK;

}

sub log_handler {
       my $r = shift;

       my $after_bytes = $gtop->proc_mem($$)->size();
       my $before_bytes = $r->pnotes("mem_usage_before_request");
       my $delta_bytes =  $after_bytes - $before_bytes;

       if ($delta_bytes > $THRESHOLD) {
           $r->log_error("[$$] url: " . $r->uri() .
                         "; before: " . format_bytes( $before_bytes ) .
                         "; after: " . format_bytes( $after_bytes ) .
                         "; delta: " . format_bytes( $delta_bytes ));
       }

       return OK;
}

1;

Reply via email to