package TestCommon::MemoryLeak; # handy functions to measure memory leaks. since it measures the total # memory size of the process and not just perl leaks, you get your # C/XS leaks discovered too # # For example to test TestAPR::Pool::handler for leaks, add to its # top: # # TestCommon::MemoryLeak::start(); # # and just before returning from the handler add: # # TestCommon::MemoryLeak::end(); # # now start the server with only worker server # # % t/TEST -maxclients 1 -start # # of course use maxclients 1 only if your test be handled with one # client, e.g. proxy tests need at least two clients. # # Now repeat the same test several times (more than 3) # # % t/TEST -run apr/pool -times=10 # # t/logs/error_log will include something like: # # size vsize resident share rss # 196k 132k 196k 0M 196k # 104k 132k 104k 0M 104k # 16k 0k 16k 0k 16k # 0k 0k 0k 0k 0k # 0k 0k 0k 0k 0k # 0k 0k 0k 0k 0k # # as you can see the first few runs were allocating memory, but the # following runs should consume no more memory. The leak tester measures # the extra memory allocated by the process since the last test. Notice # that perl and apr pools usually allocate more memory than they # need, so some leaks can be hard to see, unless many tests (like a # hundred) were run. use strict; use warnings FATAL => 'all'; # XXX: as of 5.8.4 when spawning ithreads we get an annoying # Attempt to free unreferenced scalar ... perlbug #24660 # because of $gtop's CLONE'd object, so pretend that we have no gtop # for now if perl is threaded # GTop v0.12 is the first version that will work under threaded mpms use Config; use constant HAS_GTOP => eval { !$Config{useithreads} && require GTop && GTop->VERSION >= 0.12 }; my $gtop = HAS_GTOP ? GTop->new : undef; my @attrs = qw(size vsize resident share rss); my $format = "%8s %8s %8s %8s %8s\n"; my %before; sub start { die "No GTop avaible, bailing out" unless HAS_GTOP; unless (keys %before) { my $before = $gtop->proc_mem($$); %before = map { $_ => $before->$_() } @attrs; # print the header once warn sprintf $format, @attrs; } } sub end { die "No GTop avaible, bailing out" unless HAS_GTOP; my $after = $gtop->proc_mem($$); my %after = map {$_ => $after->$_()} @attrs; warn sprintf $format, map GTop::size_string($after{$_} - $before{$_}), @attrs; %before = %after; } 1; __END__